2011-03-14 87 views
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(); } 

     ... 
}; 

我的意图是从该点上的包装,构造函数别的地方内注册的实例,并 ,它可以接收对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来实现我想要的功能,而不是 对参数有任何副作用并且也接受临时对象?

非常感谢!

+0

为了完成你想干净的工作,你需要完美的转发或继承的构造函数,C++ 03不支持这两种构造函数,但C++ 0x将支持这两种构造函数。 – 2011-03-14 22:30:20

回答

1

在C++ 03中不可能为const和非const参数的每个组合提供这样的事情,而无需手动重载。

2

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

1

没有表达式有引用类型。因此,当参数推导与参数表达式类型相关时,它不能区分ab,因为参数ab都具有相同的类型。

参考[EXPR] P5在spec

如果表达式最初具有类型为 “参照T”(8.3.2,8.5.3),所述类型被调节至T任何之前更深入的分析。

1

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

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

对于你的临时问题,使参数const引用(如Wrapper(const U &))。

事情是,临时是rvalues。该标准规定非const引用只能绑定到左值。因此,符合标准的编译器不会让您将临时对象(rvalues)作为参数传递给非const引用参数。 (这与模板无关,这是一个通用规则)。

这是我所知道的最好的,所以带着一点怀疑。