2

我有一些关于功能模板的问题。

我的计划是构建一个派生自用户定义类的包装器,不仅导出该类的公共函数,还导出它的构造函数。所以我决定使用多个构造函数模板(我认为它们的工作方式与函数模板完全相同)和 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&],这会导致传递引用到引用,这是无效的。

那么,为什么编译器会在这种情况下推导出一个值类型呢?是否可以创建一个 Wrapper-Ctor 来做我想要的,对参数没有任何副作用并且还接受临时变量?

非常感谢!

4

4 回答 4

2

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

于 2011-03-14T19:23:30.973 回答
1

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

于 2011-03-14T19:22:13.457 回答
1

有点晚了,但因为我认为这没有完全回答......

模板参数推导见前面的回答。

对于临时变量的问题,将参数设为 const 引用(如 Wrapper(const U&))。

问题是,临时变量是右值。该标准规定非常量引用只能绑定到左值。因此,符合标准的编译器不会让您将临时(右值)作为参数传递给非常量引用参数。(这与模板没有任何关系,这是一般规则)。

这是据我所知,因此请持怀疑态度。

于 2011-06-16T23:24:46.693 回答
1

没有表达式有引用类型。因此,当参数推导对参数表达式类型进行推导时,它无法区分a和,b因为参数ab两者具有相同的类型。

请参阅规范中的 [expr]p5

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

于 2011-03-14T22:12:21.967 回答