我对功能模板有一些疑问。
我的计划是构建一个从用户定义的类派生的包装器 不仅导出该类的公共函数,还导出其构造函数。 所以我决定使用多个构造函数模板(我认为它完全正常工作) 与函数模板相同)具有1到n个参数,以满足大多数构造函数的需要。
这些只是简单地调用构造函数并在之后执行其他操作,例如 这样:
template <class T>
class Wrapper : public T
{
public:
template <class U>
Wrapper(U &u) : T(u) { doSomething(); }
template <class U, class V>
Wrapper(U &u, V &v) : T(u,v) { doSomething(); }
...
};
我的目的是在其他地方的Wrapper-Ctor中注册实例, 从那时起,它可以接收对T中定义的虚函数的调用。
我必须在上面的代码中使用引用运算符,以保证这一点 我的Wrapper-Ctor对传递的参数没有任何副作用 (复制构造)。
令我惊讶的是,除了临时工之外,这总是有用的,这就是为什么 我对在这种情况下编译器推断出的类型感到困惑。 为了简化这种情况,我试图通过模板函数做类似的事情:
template <class T>
void foo(T &t)
{
int x = ""; // intentional error
}
调用这样的函数:
std::string a;
std::string &b = a;
foo(b);
令我惊讶的是,编译器在其错误消息中表示[T = std :: string]。 我本来期望这是[T = std :: string&amp;],这会导致 传递引用引用,这是无效的。
那么,为什么编译器会在这种情况下推断出一个值类型呢? 是否有可能创建一个Wrapper-Ctor,它可以做我想要的,但不是 对参数有任何副作用,也接受临时工作?
非常感谢!
答案 0 :(得分:2)
看起来C ++规范明确指出这是预期的行为。具体来说,如果你有一个模板函数,它接受一个取决于模板类型参数的参数P
,如果P
是一个引用,那么引用的基础类型,而不是引用类型,用于确定P
应使用的类型(参见§14.8.2.1/ 2)。此外,同一部分说明在此步骤中会忽略const
和volatile
限定符,因此可以自动推断const
。
答案 1 :(得分:1)
在C ++ 03中,不能为const和非const参数的每个组合手动重载提供这样的东西。
答案 2 :(得分:1)
没有表达式有引用类型。因此,当参数推导推断出参数表达式类型时,它无法区分a
和b
,因为参数a
和b
都具有相同的类型。
请参阅规范
中的[expr] p5如果表达式最初具有“对T的引用”类型(8.3.2,8.5.3),则在进行任何进一步分析之前将类型调整为T.
答案 3 :(得分:1)
有些晚了,但因为我不认为这完全得到了回答......
有关模板参数扣除,请参阅之前的答案。
对于临时问题,请使参数为const引用(如Wrapper(const U&amp;)中所示)。
事实是,临时的是左撇子。该标准规定非const引用只能绑定到左值。因此,符合标准的编译器不允许您将临时值(rvalues)作为非const引用参数的参数传递。 (这与模板没有任何关系,这是一般规则)。据我所知,这有点怀疑。