【发布时间】:2015-02-09 04:56:19
【问题描述】:
我有模板类C,它有一个非类型但引用模板参数到类型P:
class P {
public:
int x;
int y;
};
template <const P &x>
class C {
public:
const int &f() { return x.x; }
};
我声明了一个P类型的全局变量:
P p = {33,44};
我还声明了一个返回对p的引用的函数:
constexpr const P &h() { return p; }
然后尝试在下面使用这些:
C<p> o; // line 1
C<h()> oo; // line 2
当然,我对第一个实例化没有问题,但第二个实例化。我的编译器抱怨:
error: non-type template argument does not refer to any declaration
为什么会这样?我无法在规范中找到反对它的论据。我不确定这是否与Calling constexpr in default template argument 中的问题完全相同,其中讨论的是关于 nested 实例化的实例化点。这更像是一个类型问题,但是哪一个呢?我的函数h() 返回一个对定义明确的类型(const P &)的明确定义变量的引用。我预计会发生一些内联以给出正确的结果,但事实并非如此。你能告诉我为什么吗?
将函数声明为内联不会改变任何问题。
实验是用Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn 完成的。我也试过g++-mp-4.8 (MacPorts gcc48 4.8.3_2) 4.8.3,报错为:
'h()' is not a valid template argument for type 'const P&' because it is not an object with external linkage
看起来我对h() 的调用(这是一个constexpr,所以编译时可计算)不被视为这样......
我忘了说如果我们尝试像这样的另一个参考,问题是一样的:
const P &pp = p;
然后
C<pp> oo;
这次第一个编译器说:
non-type template argument of reference type 'const P &' is not an object
第二个:
error: could not convert template argument 'pp' to 'const P &'
pp 不是对象? pp 不是 const P& 类型?好吧,我可以按原样使用它...我知道它是一个参考,但与本机参考没有区别,或者?
【问题讨论】:
-
FWIW GCC 4.9.1 还说
error: ‘h()’ is not a valid template argument for type ‘const P&’ because it is not an object with external linkage -
谢谢,但
h()返回p和p有外部链接。这适用于C<p>,那么为什么不使用C<h()>。 -
我认为问题在于自从在 C++ 中引入 constexpr 以来,非类型模板参数还没有被审查过。见N3413
-
谢谢。我不确定该文档(非常有趣!)是否能回答我的问题。如果我理解它涉及类型等价/平等(这是我关心的另一个问题,但不是这个)......
-
您的代码使用
clang HEAD工作,请参阅我更新的答案中的实时示例,因此该提案不仅被接受,而且我们可以看到它也能正常工作。
标签: c++ templates c++11 language-lawyer constexpr