首页 文章

为什么clang拒绝variadic模板的朋友功能

提问于
浏览
12

我有以下示例代码,简化为必需的,编译与gcc 6.1,gcc 7.0 head和Visual Studio 2015 / 2017RC,但没有任何clang版本 .

#include <iostream>
#include <tuple>

using namespace std;

namespace outer {
  namespace test {

    template <typename A, typename B, typename...C>
    auto bar_(A&&, B&&, C&&... c) {
      return std::make_tuple(c._p...);
    }

  }

  template <typename A, typename B, typename...C>
  auto bar(A a, B b, C&&... c) {
    return test::bar_(std::move(a), std::move(b), std::forward<C>(c)...);
  }

  template<typename T>
  class foo
  {
    template <typename A, typename B, typename...C>
    friend auto test::bar_(A&&, B&&, C&&... c);

    int _p;
  public:
    foo(int f) : _p(f) {}
  };
}

int main() {
  outer::foo<int> a1(1);
  outer::foo<int> a2(2);

  auto result = outer::bar(2.3, 4.5, a1, a2);
  cout << get<0>(result) << " " << get<1>(result) << '\n';

  return 0;
}

clang告诉我:prog.cc:12:34:错误:'_ p'是'outer :: foo'的私有成员return std :: make_tuple(c._p ...);

我不明白为什么clang不承认朋友的声明 . 这是一个铿锵的错误还是所有其他编译器的问题?

当我使foo成为非模板类时,clang不会抱怨 . 任何解决方法的想法?

提前谢谢了

2 回答

  • 1

    由于"why?"问题在this thread深入讨论过,我将只关注可能的解决方法 . 您可以尝试将函数包装到虚拟结构中,以确保它的所有可能重载也包含在 foo 的友元列表中 . 解决方案主张可能如下所示:

    #include <iostream>
    #include <tuple>
    
    using namespace std;
    
    namespace outer {
      namespace test {
    
        struct wrapper{
          template <typename A, typename B, typename...C>
          static auto bar_(A&&, B&&, C&&... c) {
            return std::make_tuple(c._p...);
          }
        };
    
      }
    
      template <typename A, typename B, typename...C>
      auto bar(A a, B b, C&&... c) {
        return test::wrapper::bar_(std::move(a), std::move(b), std::forward<C>(c)...);
      }
    
      template<typename T>
      class foo
      {
        friend struct test::wrapper;
    
        int _p;
      public:
        foo(int f) : _p(f) {}
      };
    }
    
    int main() {
      outer::foo<int> a1(1);
      outer::foo<int> a2(2);
    
      auto result = outer::bar(2.3, 4.5, a1, a2);
      cout << get<0>(result) << " " << get<1>(result) << '\n';
    
      return 0;
    }
    

    [live demo]

  • 1

    在我看来,这是一个铿锵的错误( _pprivate ,但 bar_() 应该是 friend 类的 friend 函数) .

    解决方法是在 foo 中添加一个getter getP()

    template<typename T>
    class foo
    {
    //    template <typename A, typename B, typename...C>
    //    friend auto outer::test::bar_(A&&, B&&, C&&... c);
    
      int _p;
    public:
      foo(int f) : _p(f) {}
    
      int getP () const  //  <--- added getP()
       { return _p; }
    };
    

    并在 bar_() 中使用它

    template <typename A, typename B, typename...C>
    auto bar_(A&&, B&&, C&&... c) {
      return std::make_tuple(c.getP()...);
    }
    

相关问题