最近,我对现代c++进行了研究。我在[49:00]看到了有关c++ 11/c++ 14可变参数模板的video。如果要使用可变参量模板计算不同类型(例如intdouble)的元组的总和,请使用c++ 11,该视频提供了一种解决方案:

struct Sum
{
    template<typename T>
    static T sum(T n)
    {
        return n;
    }

    template<typename T, typename... Args>
    static auto sum(T n, Args... rest) -> decltype(n+sum(rest...))
    {
        return n + sum(rest...);
    }
}
auto x = Sum::sum(1, 2.5, 3);
auto无法推断出c++11中的返回类型,因此您必须使用decltype声明返回类型。但是某些编译器构建失败,某些编译器构建成功。 link

尽管使用auto to deduce return type没问题,但我的问题是:
  • c++11标准涵盖了这个问题吗?如果不是,那么编译器是否通过自己的实现来解决问题?
  • 为什么最新版本的gcc 8.1编译失败,而gcc 4/5/6/7编译成功? gcc是否存在任何兼容性问题?

  • 顺便说一句,编译错误消息是:

    最佳答案

    此处以尾随返回类型查找功能名称,

    template<typename T, typename... Args>
    static auto sum(T n, Args... rest) -> decltype(n+sum(rest...))
    

    在声明此sum之前的上下文中完成,以及通过ADL(依赖于参数的查找)完成。

    而且,由于在有关类型的调用点无法通过ADL看到此模板,因此该模板无法编译是适当的。

    较早的gcc编译器可能除了应该使用的上下文之外,还使用对象上下文。这是一个合理的错误。

    您可以轻松解决此问题:
    struct Sum {
    private:
      template<typename T>
      friend T summer(Sum, T n) {
        return n;
      }
      template<typename T, typename... Args>
      friend auto summer(Sum, T n, Args... rest) -> decltype(n+summer(Sum{},rest...)) {
        return n + summer(Sum{},rest...);
      }
    public:
      template<class...Args>
      auto sum(Args...args)->decltype(summer(Sum{}, args...)){
        return summer(Sum{}, args... );
      }
    };
    

    在这里,我们在一些私有(private) friend 中强制使用ADL。这允许夏季的重载以其尾随的返回类型“看到自己”。

    关于c++ - 使用c++ 11的不同输入类型的C++可变参数模板,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50206610/

    10-11 23:23
    查看更多