键入函数模板参数的推导

时间:2011-03-14 19:18:06

标签: c++ templates function types inference

我对功能模板有一些疑问。

我的计划是构建一个从用户定义的类派生的包装器 不仅导出该类的公共函数,还导出其构造函数。 所以我决定使用多个构造函数模板(我认为它完全正常工作) 与函数模板相同)具有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(); }

        ...
};

我的目的是在其他地方的W​​rapper-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,它可以做我想要的,但不是 对参数有任何副作用,也接受临时工作?

非常感谢!

4 个答案:

答案 0 :(得分:2)

看起来C ++规范明确指出这是预期的行为。具体来说,如果你有一个模板函数,它接受一个取决于模板类型参数的参数P,如果P是一个引用,那么引用的基础类型,而不是引用类型,用于确定P应使用的类型(参见§14.8.2.1/ 2)。此外,同一部分说明在此步骤中会忽略constvolatile限定符,因此可以自动推断const

答案 1 :(得分:1)

在C ++ 03中,不能为const和非const参数的每个组合手动重载提供这样的东西。

答案 2 :(得分:1)

没有表达式有引用类型。因此,当参数推导推断出参数表达式类型时,它无法区分ab,因为参数ab都具有相同的类型。

请参阅规范

中的[expr] p5
  

如果表达式最初具有“对T的引用”类型(8.3.2,8.5.3),则在进行任何进一步分析之前将类型调整为T.

答案 3 :(得分:1)

有些晚了,但因为我不认为这完全得到了回答......

有关模板参数扣除,请参阅之前的答案。

对于临时问题,请使参数为const引用(如Wrapper(const U&amp;)中所示)。

事实是,临时的是左撇子。该标准规定非const引用只能绑定到左值。因此,符合标准的编译器不允许您将临时值(rvalues)作为非const引用参数的参数传递。 (这与模板没有任何关系,这是一般规则)。

据我所知,这有点怀疑。