函数模板参数的类型推导
我有一些关于函数模板的问题。
我的计划是构建一个派生自用户定义的类的包装器 不仅导出该类的公共函数,还导出其构造函数。 所以我决定使用多个构造函数模板(我认为它们完全可以工作) 与函数模板相同),具有 1 到 n 个参数,可以满足大多数构造函数的需求。
这些将不仅仅是简单地调用构造函数并在之后执行其他操作,例如 this:
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 来执行我想要的操作,而不是 对参数有任何副作用并且还接受临时参数吗?
多谢!
I have some questions concerning function templates.
My plan was to build a wrapper which derives from a user-defined class and
not only exports the public functions of that class but also its constructors.
So I decided I would use multiple constructor templates (which I presume work exactly
the same as function templates) with 1 to n parameters to satisfy most constructors needs.
These would than simply call the constructor and do something else afterwards, like
this:
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(); }
...
};
My intent is to register the instance within the Wrapper-Ctor somewhere else and,
from that point on, it can receive calls to virtual functions defined in T.
I had to use the reference operator in the code above, in order to guarantee that
my Wrapper-Ctor does not have any side-effects on the parameters that were passed
(copy-construction).
To my surprise this always worked, except for temporaries, which is the reason why
I am confused about the types that are inferred by the compiler in this situation.
To simplify the situation I tried to do something similiar via a template function:
template <class T>
void foo(T &t)
{
int x = ""; // intentional error
}
Calling the function like this:
std::string a;
std::string &b = a;
foo(b);
To my surprise the compiler denotes [T = std::string] in its error message.
I would have expected for this to be [T = std::string&], which would have caused
passing a reference-to-reference, which is invalid.
So, why does the compiler deduce a value-type in this situation?
Is it even possible to create a Wrapper-Ctor that does what I want, does not
have any side-effects on the parameters and also accepts temporaries?
Thanks alot!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
看起来 C++ 规范明确指出这是预期的行为。具体来说,如果您有一个模板函数,它接受依赖于模板类型参数的参数
P
,如果P
是引用,则引用的基础类型,而不是引用类型,用于确定P
应使用什么类型(请参阅第 14.8.2.1/2 节)。此外,同一部分还指出,在此步骤中将忽略 const 和 volatile 限定符,因此可以自动推断 const 性。It looks like the C++ spec explicitly states that this is the intended behavior. Specifically, if you have a template function that takes in a parameter
P
that depends on a template type argument, ifP
is a reference, then the underlying type of the reference, rather than the reference type, is used to determine what type should be used forP
(see §14.8.2.1/2). Moreover, this same section says thatconst
andvolatile
qualifiers are ignored during this step, so theconst
ness can be inferred automatically.在 C++03 中,如果不手动重载 const 和非常量参数的每个组合,就不可能提供这样的东西。
It is not possible in C++03 to provide such a thing without manually overloading for every combination of const and non-const parameters.
没有任何表达式具有引用类型。因此,当参数推导针对参数表达式类型进行推导时,无法区分
a
和b
,因为参数a
和b
两者具有相同的类型。请参阅规范中的 [expr]p5
No expression ever has reference type. Therefor, when argument deduction deduces against the argument expression type, it cannot make a distinction between
a
andb
because the argumentsa
andb
both have the same type.Refer to [expr]p5 in the spec
有点晚了,但因为我认为这没有得到完全回答...
有关模板参数推导,请参阅前面的答案。
对于临时变量的问题,请将参数设置为 const 引用(如 Wrapper(const U&) 中所示)。
问题是,临时变量是右值。该标准规定非常量引用只能绑定到左值。因此,符合标准的编译器不会让您将临时值(右值)作为参数传递给非常量引用参数。 (这与模板没有任何关系,这是一般规则)。
据我所知,所以对此持怀疑态度。
Somewhat late, but since I don't think this was answered completely...
For template parameter deduction, see the previous answers.
For your problem with temporaries, make the parameters const references (as in Wrapper(const U&)).
The thing is, temporaries are rvalues. The standard states that non-const references can only be bound to lvalues. Therefore, a standards compliant compiler won't let you pass temporaries(rvalues) as arguments to non-const reference parameters. (This doesn't have anything to do with templates in particular, it's a general rule).
This is to the best of my knowledge, so take it with a bit of scepticism.