【发布时间】:2016-05-11 14:04:49
【问题描述】:
似乎无法将引用传递给 派生对象的基类对象作为模板参数, 正如我在这里尝试做的那样:
struct a
{ int _v;
constexpr a():_v(0){}
constexpr a(int v): _v(v){}
};
struct c: public a
{ constexpr c():a(){}
constexpr c(int v):a(v){}
};
extern const c default_a;
constexpr const c default_a { 1 };
const a& c_as_a = default_a;
// ^-- this line (16) causes no error - c can be converted to a
template < const a & The_A = default_a >
struct b
{ constexpr static const a &the_a = The_A;
};
b<> a_b;
// Template instantiation causes error:
// t.C:24:7: error: could not convert template argument 'default_a' to 'const a&'
// b<> a_b;
// ^
我本来期望'c'对象'default_a',因为它是从 'a',可以作为 'const a&' 被接受,因为它在第 16 行。
为什么这不能作为模板参数?
规范的哪一部分实际上要求这种行为?
也许我构建的 gcc-5.3.0 存在某种缺陷?
有人找到了将派生对象作为基类对象引用模板参数传递的好方法/方法吗?
我不能只用引用变量 'c_as_a' 代替 'default_a' 模板参数列表:
template < const a & The_A = c_as_a >
t.C:24:7: 错误:'const a& c_as_a' 不是类型 'const a&' 的有效模板参数,因为引用变量没有常量地址 b a_b;
我也不能替换任何类似的 constexpr 函数调用:
constexpr const a& c_as_a( const c &c ){ return *reinterpret_cast<const a*>(&c);}
...
template < const a & The_A = c_as_a( default_a ) >
因为此调用不是“具有外部链接的对象”。
任何关于如何实现将派生对象的基类的引用作为模板参数传递的建议将不胜感激 - 它是 必须是可能的,我只是看不到ATM。
必须有一种方法可以将对象的基类对象的引用指定为模板参数。
【问题讨论】:
-
在 C++14 中,非类型模板参数
const a &只能通过链接直接绑定到命名的左值。所以你运气不好。在 C++17 中,这将被允许绑定到更多的东西,see here -
感谢 M.M - 很抱歉最初的“The_A = c”错字 - 现在更正了。
-
好的,感谢您确认我的怀疑。
-
实际上我不太确定,我在 C++14 标准中看不到为什么不应该接受
default_a。它是一个带链接的命名左值,它的地址是一个常量表达式 -
可能是 [temp.arg.nontype]/5.3:“对于对象类型引用的非类型模板参数,不适用任何转换。” (因此不允许执行从派生到基础引用的转换)
标签: c++