【问题标题】:Type deduction of function template parameters函数模板参数的类型推导
【发布时间】:2011-07-15 06:29:20
【问题描述】:

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

我的计划是构建一个派生自用户定义类的包装器,并且 不仅导出该类的公共函数,还导出其构造函数。 所以我决定我会使用多个构造函数模板(我认为它们完全可以工作 与函数模板相同)具有 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,不 对参数有任何副作用并且还接受临时变量?

非常感谢!

【问题讨论】:

  • 为了干净利落地做你想做的事,你需要完美的转发或继承构造函数,C++03 都不支持,但在 C++0x 中会支持。

标签: c++ templates function types inference


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    参考规范中的[expr]p5

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-09-19
          • 2018-12-05
          • 1970-01-01
          • 2014-04-17
          • 2020-07-09
          • 1970-01-01
          • 2021-05-23
          相关资源
          最近更新 更多