示例代码中的变量v
odr-used ?
extern void* v;
template<void*&>
void f() {}
int main()
{
f<v>();
}
我在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-used ,即使它们未在模板体中引用,因此Boost ML&#39; s模式是不正确的。
我的理解是否正确?
答案 0 :(得分:7)
我相信v
odr-used 。 f<v>
是 template-id ( 14.2 ), template-argument 是 id-expression ( 5.1.1 ) - 一种表达形式。它显然不是未评估的操作数(它不会显示为typeid
,sizeof
,noexcept
或decltype
的操作数,因此它&# 39; s 可能评估每 3.2 / 2 :
3.2 / 2 表达式可能被评估,除非它是未评估的操作数(第5条)或其子表达式......
此时,我们有
3.2 / 3 变量
x
的名称显示为潜在评估的表达式ex
odr-used 除非[条件似乎没有在此处应用,因为没有应用左值到右值的转换]。
答案 1 :(得分:2)
[basic.def.odr] / 3:
变量
x
,其名称显示为可能已评估的表达式 除非应用左值到右值转换,否则ex
ex
odr-used (4.1)到x
产生一个常量表达式(5.19) [..]
不幸的是,此时将l-t-r转换应用于v
不会产生常量表达式 - [expr.const] / 2:
条件表达式
e
是核心常量表达式,除非e
的评估,遵循抽象机器的规则 (1.9),将评估以下表达式之一:[..]
- 一个 左值 - 右值转换(4.1),除非它适用于
- 初始化
整数或枚举类型的非易失性glvalue,它引用具有前一个的非易失性const对象 初始化,使用常量表达式[..]或
非易失性glvalue ,指的是使用
constexpr
定义的非易失性对象,或者引用 到这种对象的不可变子对象,或- 文字类型的非易失性glvalue,引用一个非易失性对象,其生命周期始于
e
的评估范围内;
然而,虽然Matt建议的实施并不正确,但这个想法当然是。使用帮助器模板在this answer中演示了使用此方法的简单方法。在您的情况下,请尝试
template <bool cond, int id=0>
using distinct_enable_if =
typename std::enable_if<cond, std::integral_constant<int,id>*>::type;
class test
{
public:
template< class... T,
distinct_enable_if<sizeof...(T) == 10> = nullptr>
test( T&&... ) {}
template< class T,
distinct_enable_if<std::is_arithmetic<T>{}> = nullptr>
operator T() const { return T{}; }
/* Note the additional template argument:
It ensures that the template parameter lists are not identical,
and the ODR isn't violated */
template< class T,
distinct_enable_if<std::is_pointer<T>{}, 1> = nullptr>
operator T() const { return T{}; }
};