2014-11-04 53 views
1

我试图禁止引用一个类,我已经看到一些奇怪的行为。我已经构建了一个玩具示例来展示发生了什么。如果我有这样的:static_assert是否需要使用模板参数?

template <class T> 
struct something { 
}; 

template <class T> 
struct something<T&> { 
    static_assert(false, "reference disallowed with something"); 
}; 


int main() { 
    something<int> a; (void)a; 
} 

即使我不声明某个实例与参考,但仍然失败:

> g++ -std=c++11 foo.cc -o foo 
foo.cc:7:5: error: static assertion failed: reference disallowed with something 
    static_assert(false, "reference disallowed with something"); 
    ^

如果我调整,以便它具有使用模板参数通过代理类,然后它的工作原理:

template <class T> 
struct something { 
}; 

template <class T> 
struct something<T&> { 
    template <class TT> struct falsity { 
     static const bool value = false; 
    }; 
    static_assert(falsity<T>::value, "reference disallowed with something"); 
}; 

int main() { 
    something<int> a; (void)a; 
} 

然后它工作得很好,这是预期的行为?我会认为静态断言不管是什么类的成员。

编辑:这是gcc版本4.8.2(Ubuntu的4.8.2-19ubuntu1)

+0

简而言之:没有!试试'static_assert(false,“这是假的。”);' – 2014-11-04 01:36:12

+0

@πάνταῥεῖ:我不确定我理解,你不认为这是预期的行为?我应该在哪里尝试你的断言? – 2014-11-04 01:44:25

+0

_“我应该在哪里试试你的断言?”_其他地方。要点是:**它不需要使用模板参数。** – 2014-11-04 01:46:17

回答

3

static_assert不依赖于任何模板参数,所以编译器不必等到类模板的实例化评估声明。相反,它在two phase name lookup的第一阶段执行此操作,并且代码无法编译。

在你的情况,你可以通过改变断言修复故障

static_assert(!std::is_lvalue_reference<T>::value, "reference disallowed with something"); 
+0

Ah OK很有道理,听起来像是你需要使用模板参数,或者你基本上会抛出断言而不管实例化类。 – 2014-11-04 01:58:27

+0

@gct对,通过使条件依赖在模板参数上,编译器必须等到模板实例化以评估表达式。 – Praetorian 2014-11-04 01:59:57

+1

花了我一段时间挖掘引用标准:14.6/8 *如果没有有效的专业化可以为模板定义生成,并且该模板没有实例化,则模板定义不合格,不需要诊断。*这是问题中的情况,由于'static_assert'不依赖于模板参数,所以不能从该定义生成任何*有效的特化。 – 2014-11-04 02:13:04

相关问题