为什么使用带有 gcc 和模板函数的两个或多个基于 typedef 的静态断言时会出现"conflicting declaration"错误?
Why do I get "conflicting declaration" error using two and more typedef-based static asserts with gcc and template function?
我有以下代码(不,模板没有在任何地方实例化):
#define cAssert( expr ) typedef char __C_ASSERT__[( expr )?1:-1]
template<int t>
void f()
{
cAssert( t != 0 );
cAssert( t != 2 );
}
它与Visual C++一起编译得很好(当然,当t
既不是0也不是2时)。然而,gcc(4.9.0 及更早版本 - 您可以在 http://gcc.godbolt.org/上测试它们)输出以下内容:
In function ‘void f()’:
1 : error: conflicting declaration ‘typedef char __C_ASSERT__ [((t != 2) ? 1 : (-1))]’
#define cAssert( expr ) typedef char __C_ASSERT__[( expr )?1:-1]
如果我只留下一个cAssert()
(两个中的任何一个) - 它可以很好地编译。只有当我同时拥有它们时,问题才存在。
为什么 gcc 会拒绝此代码,我该如何解决此问题?
我不知道
为什么这不起作用。
一个半修复:
#define cAssertbraces( expr ) typedef char __C_ASSERT_BRACES__[( expr )?1:-1]
template<class T>
void cAssert(T v1, T v2) { {cAssertbraces( v1 != v2 );} }
template<int t>
void f()
{
{cAssertbraces( t != 0 );}
{cAssertbraces( t != 2 );}
cAssert(t, 0);
cAssert(t, 2);
}
或者,使用如下__LINE__
:
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(!!(COND))*2-1]
#define COMPILE_TIME_ASSERT3(X,L) STATIC_ASSERT(X,static_assertion_at_line_##L)
#define COMPILE_TIME_ASSERT2(X,L) COMPILE_TIME_ASSERT3(X,L)
#define COMPILE_TIME_ASSERT(X) COMPILE_TIME_ASSERT2(X,__LINE__)
...
COMPILE_TIME_ASSERT( t != 2 );
我从这个问题中得到了(那里的答案很好,应该检查)。
GCC 拒绝代码的原因本质上是,在宏展开后,您有一个不同的标记序列,其中包含该类型的声明。考虑一个更简单的例子:
template <unsigned t>
void f()
{
using type = int[t + 0];
using type = int[t ]; // Adding a +0 here makes GCC compile it fine
}
海湾合作委员会抱怨。然而,核心问题 422 涵盖了这一点,CWG 在该问题上得出结论:
我们认为,所有这些情况都应该被允许,并且只有在生成模板的实例时才需要错误。目前的标准措词似乎并不禁止这种情况,因此不需要改变。
也就是说,海湾合作委员会是错误的。
相关文章:
- 尝试使用 std::vector<std::thread时出现静态断言失败错误>
- uint_not_usable_without_attribute在业力规则中使用数字生成器时静态断言失败
- 初始值设定项列表构造和静态断言
- 如何在 c++11 中静态断言 std::array 类成员进行排序?
- 我如何静态断言static_cast是 noexcept?
- 绕过特征静态断言
- Qt C++:静态断言失败:信号和插槽参数不兼容
- 捕获的静态断言 lambda
- 静态断言添加操作是否可用
- 错误:静态断言失败:std ::线程参数必须在转换为rvalues后不可行
- 是否允许编译器在静态断言中评估重言式
- 公共继承的静态断言
- 静态断言失败,出现"Windows headers require the default packing option..."
- 静态断言,如果在编译时不知道表达
- 如果标头包含在另一个标头中,但不包含 CPP,则静态断言
- 静态断言 std::array 的大小,其类型是使用 decltype 从成员函数的返回值中获取的
- 围绕静态断言不完整的类型
- C 11多态映射键静态断言失败:哈希函数必须与密钥类型的参数无关
- 包含多态对象的向量:静态断言误差
- 与复制构造函数不同的移动构造函数的静态断言