函数模板参数的类型推导

发布于 2024-10-21 22:21:44 字数 1115 浏览 2 评论 0原文

我有一些关于函数模板的问题。

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

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

青衫负雪 2024-10-28 22:21:44

看起来 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, if P is a reference, then the underlying type of the reference, rather than the reference type, is used to determine what type should be used for P (see §14.8.2.1/2). Moreover, this same section says that const and volatile qualifiers are ignored during this step, so the constness can be inferred automatically.

羞稚 2024-10-28 22:21:44

在 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.

泛滥成性 2024-10-28 22:21:44

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

请参阅规范中的 [expr]p5

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

No expression ever has reference type. Therefor, when argument deduction deduces against the argument expression type, it cannot make a distinction between a and b because the arguments a and b both have the same type.

Refer to [expr]p5 in the spec

If an expression initially has the type "reference to T" (8.3.2, 8.5.3), the type is adjusted to T prior to any further analysis.

嘴硬脾气大 2024-10-28 22:21:44

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

有关模板参数推导,请参阅前面的答案。

对于临时变量的问题,请将参数设置为 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文