【问题标题】:C++ compile time checker using templates使用模板的 C++ 编译时检查器
【发布时间】:2011-02-27 10:34:10
【问题描述】:

我有以下取自现代 C++ 设计的代码。当我使用它时,我得到了编译错误,我认为无效的 sizeof 操作数。任何人都可以指出是什么问题。谢谢!

template<bool>
struct CompileTimeChecker {
    CompileTimeChecker(...);
};

template<>
struct CompileTimeChecker<false> {
};

#define STATIC_CHECK(expr, msg) \
{\
class ERROR_##msg {}; \
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg())));\
}

template <class To, class From>
To safe_reinterpret_cast(From from) {
    STATIC_CHECK(sizeof(From) <= sizeof(To), Destination_Type_Too_Narrow);
    return reinterpret_cast<To>(from);
}

int main(void)
{
    int a[20];
    void* somePointer = a;
    char c = safe_reinterpret_cast<int>(somePointer);
}

错误:

d:\technical\c++study\readparsing\readparsing\addressconv.cpp(29) : 错误 C2066: 转换为函数类型是非法的 1> d:\technical\c++study\readparsing\readparsing\addressconv.cpp(37) : 参见正在编译的函数模板实例化 'To safe_reinterpret_cast(From)' 的参考 1> 与 1> [ 1> 到 = 整数, 1> 来自=无效 * 1>] 1>d:\technical\c++study\readparsing\readparsing\addressconv.cpp(29) : 错误 C2070: 'CompileTimeChecker<__formal> (safe_reinterpret_cast::ERROR_Destination_Type_Too_Narrow (__cdecl *)(void))': 非法操作数大小 1> 与 1> [ 1> __正式=真 1>]

【问题讨论】:

  • 我猜这是在典型机器上的 64 位编译?如果是这样,void* 可能是 8 个字节,而int 将是 4 个字节,从而触发断言。

标签: c++ most-vexing-parse


【解决方案1】:

对最令人头疼的解析又一次打击......

sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))

是一样的

class Foo {};
class Bar {};
sizeof(Foo((Var()));

因为 Foo(Var) 可以被解释为一个类型(函数接受一个(没有参数的函数返回一个 Var)并返回一个 Foo),就是这样。

【讨论】:

  • 这与问题有什么关系,你能详细说明一下吗
  • 这解释了“非法大小的操作数”错误。 sizeof 可以将类型作为参数,但不能作为函数类型。这就是你错误地给它的东西。
  • Foo((int())) 不是函数类型。 “参数”周围有一对括号,使其不是参数声明。
  • 啊 nvm 它是一个绑定括号。我错了:)
【解决方案2】:

就像 AProgrammer 指出的那样,(void)sizeof 不会被编译器吞噬。我建议从 sizeof 中删除括号,如下所示:

(void)sizeof CompileTimeChecker<(expr) != 0>((ERROR_##msg()));\

这似乎让 g++ 接受它,并按照它可能的意思解释它。

如果 (void)sizeof 一直给您带来麻烦,您也可以在没有它的情况下获得静态检查功能,例如通过初始化 CompileTimeChecker 变量:

CompileTimeChecker<(expr) != 0> a((ERROR_##msg()));\

【讨论】:

    猜你喜欢
    • 2014-03-31
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多