Mit*_*iya 14 c++ boost language-lawyer
v下面的示例代码中的变量是否使用了odr?
extern void* v;
template<void*&>
void f() {}
int main()
{
f<v>();
}
Run Code Online (Sandbox Code Playgroud)
我在Boost ML中发现了这种模式.
比照 http://lists.boost.org/Archives/boost/2011/04/180082.php
它表示boost::enabler永远不会定义,但如果提供选项,clang会将其拒绝为链接错误-g.
比照 http://melpon.org/wandbox/permlink/nF45k7un3rFb175z
上面的示例代码是Boost ML代码的缩减版本,clang也拒绝它.
比照 http://melpon.org/wandbox/permlink/ZwxaygXgUhbi1Cbr
我认为(但我不确定)参考类型的模板非类型参数是odr使用的,即使它们未在模板体中引用,因此Boost ML的模式是错误的.
我的理解是否正确?
我相信v是有用的.f<v>是一个template-id(14.2),其template-argument是一个id-expression(5.1.1) - 一种表达形式.这显然不是一个未计算的操作数(它不显示为的操作数typeid,sizeof,noexcept或decltype),所以它可能评估每3.2/2:
3.2/2表达式可能被评估,除非它是未评估的操作数(第5条)或其子表达式......
在这一点上,我们有
3.2/3一个
x名称显示为可能被评估的表达式的变量ex是odr-used,除非[这里似乎没有应用的条件没有应用左值到右值的转换].
[basic.def.odr]/3:
\n\n\n\n\n名称
\nx显示为潜在计算表达式的变量\nex会被 odr 使用,ex除非应用左值到右值转换\n (4.1) 生成x常量表达式 (5.19) [..]
不幸的是,此时应用 ltr 转换v不会产生常量表达式 - [expr.const]/2:
\n\n\n条件表达式
\n\ne是核心常量表达式,除非\n 的计算e遵循抽象机的规则\n (1.9),将计算以下表达式之一:[..]\xe2\x80\x94 一个\n 左值到右值的转换 (4.1),除非它应用于
\n\n\n
\n- \n
整型或枚举类型的非易失性泛左值,引用具有前面\n初始化的非易失性 const 对象,并使用常量表达式 [..] 进行初始化,或者
- \n
一个非易失性泛左值,它引用用 定义的非易失性对象
constexpr,或者引用\n 此类对象的非可变子对象,或者- 文字类型的非易失性泛左值,引用其生命周期开始于 的求值内的非易失性对象
\ne;
然而,尽管马特建议的实现并不正确,但这个想法肯定是正确的。此答案中演示了使用此方法的一种简单方法,即使用帮助程序模板。对于你的情况,尝试
\n\ntemplate <bool cond, int id=0>\nusing distinct_enable_if =\n typename std::enable_if<cond, std::integral_constant<int,id>*>::type;\n\nclass test\n{\npublic:\n template< class... T,\n distinct_enable_if<sizeof...(T) == 10> = nullptr> \n test( T&&... ) {}\n\n template< class T,\n distinct_enable_if<std::is_arithmetic<T>{}> = nullptr>\n operator T() const { return T{}; }\n\n /* Note the additional template argument:\n It ensures that the template parameter lists are not identical, \n and the ODR isn\'t violated */\n template< class T,\n distinct_enable_if<std::is_pointer<T>{}, 1> = nullptr>\n operator T() const { return T{}; }\n};\nRun Code Online (Sandbox Code Playgroud)\n\n演示。
\n| 归档时间: |
|
| 查看次数: |
174 次 |
| 最近记录: |