引用类型和odr使用的模板非类型参数

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的模式是错误的.

我的理解是否正确?

Igo*_*nik 7

我相信v有用的.f<v>是一个template-id(14.2),其template-argument是一个id-expression(5.1.1) - 一种表达形式.这显然不是一个未计算的操作数(它不显示为的操作数typeid,sizeof,noexceptdecltype),所以它可能评估3.2/2:

3.2/2表达式可能被评估,除非它是未评估的操作数(第5条)或其子表达式......

在这一点上,我们有

3.2/3一个x名称显示为可能被评估的表达式的变量exodr-used,除非[这里似乎没有应用的条件没有应用左值到右值的转换].


Col*_*mbo 2

[basic.def.odr]/3:

\n\n
\n

名称x显示为潜在计算表达式的变量\n ex被 odr 使用ex 除非应用左值到右值转换\n (4.1) 生成x常量表达式 (5.19) [..]

\n
\n\n

不幸的是,此时应用 ltr 转换v不会产生常量表达式 - [expr.const]/2:

\n\n
\n

条件表达式 e是核心常量表达式,除非\n 的计算e遵循抽象机的规则\n (1.9),将计算以下表达式之一:[..]

\n\n

\xe2\x80\x94 一个\n 左值到右值的转换 (4.1),除非它应用于

\n\n
    \n
  • 整型或枚举类型的非易失性泛左值,引用具有前面\n初始化的非易失性 const 对象,并使用常量表达式 [..] 进行初始化,或者

  • \n
  • 一个非易失性泛左值,它引用用 定义的非易失性对象constexpr,或者引用\n 此类对象的非可变子对象,或者

  • \n
  • 文字类型的非易失性泛左值,引用其生命周期开始于 的求值内的非易失性对象e
  • \n
\n
\n\n

然而,尽管马特建议的实现并不正确,但这个想法肯定是正确的。此答案中演示了使用此方法的一种简单方法,即使用帮助程序模板。对于你的情况,尝试

\n\n
template <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};\n
Run Code Online (Sandbox Code Playgroud)\n\n

演示

\n