为什么使用带有 gcc 和模板函数的两个或多个基于 typedef 的静态断言时会出现"conflicting declaration"错误?

Why do I get "conflicting declaration" error using two and more typedef-based static asserts with gcc and template function?

本文关键字:断言 静态 typedef 错误 declaration conflicting 两个 gcc 为什么 函数      更新时间:2023-10-16

我有以下代码(不,模板没有在任何地方实例化):

#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 在该问题上得出结论:

我们认为,所有这些

情况都应该被允许,并且只有在生成模板的实例时才需要错误。目前的标准措词似乎并不禁止这种情况,因此不需要改变。

也就是说,海湾合作委员会是错误的。