【问题标题】:Function template return type deduction函数模板返回类型推导
【发布时间】:2017-01-02 12:22:01
【问题描述】:

我有一些类 Cconst 和非 const 一些泛型类型 Node 的吸气剂:

template <typename NodeType>
class CParent{};

class Node {};

class C : public CParent<Node> {
    Node&       getNode(Index i);
    const Node& getNode(Index i) const;
};

现在我想创建一个别名函数,为 C 类的对象调用 getNode

template <class CType>
NodeType& AliasGetNode(CType* cobject);

但是我如何推断NodeType?也就是说,如果我打电话给AliasGetNode&lt;const C&gt;(c)AliasGetNode&lt;C&gt;(c)NodeType应该分别是const Node&amp;Node&amp;

我该怎么做?

我尝试了result_ofdecltype 方法,但没有成功。

【问题讨论】:

  • I tried the result_of and decltype approaches but have not been successful. 您应该发布您尝试过的什么,以及发生了什么。只是对事物进行模糊的暗示并说它们不起作用是没有用的。我的意思是,我猜你刚刚收到了 49 屏模板错误,但如果能确定一下就好了!
  • @underscore_d 是肯定的。但是在这种情况下,由于我希望解决方案很简单,所以我试图避免 49 屏幕的混乱。另外,关于result_ofdecltype 主题有很多具体问题没有专门解决我的问题,我会得到一个错误的“重复”问题标记

标签: c++ c++11 templates c++14


【解决方案1】:

让编译器推导出返回类型(从 C++14 开始):

template <class CType>
decltype(auto) AliasGetNode(CType& cobject)
{
    return cobject.getNode(0);
}

【讨论】:

  • 不错!在 c++11 中你也可以做 auto AliasGetNode(CType&amp; cobject) -&gt; decltype(cobject.getNode(0))
  • 它们的行为方式相同。如果decltype(auto) 没有解析为引用类型,两者都返回一个副本。因此auto &amp; 更适合 OP。
  • @StoryTeller 这听起来像是一个错误在到达单元测试之前就停止了。
  • @Potatoswatter - 还有麻烦。 decltype(auto) 将在 OP 的情况下推断出引用类型。如果 OP 需要按值返回,它将正确推断 Node。这不是滥用。 OP 希望准确返回声明的getNode() 类型。 decltype(auto) 是正确的推论。
  • @Potatoswatter - 你有那个提议的参考吗?听起来很有趣。
【解决方案2】:

我会推荐:

template <class CType>
auto AliasGetNode(CType& cobject) -> decltype(cobject.getNode(0))
{
    return cobject.getNode(0);
}

从 c++11 开始,这应该可以正常工作

【讨论】:

  • 选择这个作为不使用 C++14 的答案,虽然这似乎是一种解决方法
  • 为什么不使用 C++14 会使这更正确?如果有的话,那就更糟了,你确实在你的问题中标记了c++14
【解决方案3】:

定义一个简单的辅助特征,它将根据另一个类型是否为const,从一个类型中添加/删除const

template <class Src, class Dst>
using copy_const = typename std::conditional<
  std::is_const<Src>::value,
  const Dst,
  typename std::remove_const<Dst>::type
>::type;

并使用它:

template <class CType>
copy_const<CType, NodeType>& AliasGetNode(CType* cobject);

【讨论】:

    【解决方案4】:

    从 C++14 开始,函数的返回类型可以由编译器推断:

    template<typename CType>
    decltype(auto) AliasGetNode(CType& cobject) {
        return cobject.getNode();
    }
    

    当您在Node 类型的对象上调用AliasGetNode 时,CType 被推导出为Node。但是如果你在const Node类型的对象上调用AliasGetNodeCType会被推导出为const Node

    AliasGetNode 的返回类型设为decltype(auto) 很重要,否则您将错过返回类型的引用和常量。

    【讨论】:

    • decltype(auto) 不保证引用返回类型。 auto &amp;auto const &amp; 做。
    • @Potatoswatter 为什么不呢?你能解释一下吗?
    【解决方案5】:

    你应该写两个别名函数,一个用于非 const 实例,另一个用于 const 实例:

    template <class CType>
    const NodeType& AliasGetNode(const CType* cobject) const;  // for const instance. 
    // The function must be const since the only difference between return type will cause redefinition error.
    
    template <class CType>
    NodeType& AliasGetNode(CType* cobject);  // for non-const instance
    

    如果有重载函数,声明为 const 的实例将调用 const 函数。当然,非常量实例会调用非常量版本的重载函数。例如:

    class Aclass {
        public:
           string test() { return "calling non-const function"; }
           string test() const { return "calling const function"; }
    };
    
    int main() {
        Aclass a;
        const Aclass b;
    
        cout << a.test() << endl;
        cout << b.test() << endl;
    
        return 0;
    }
    

    结果将是:

    calling non-const function
    calling const function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-12
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多