当前位置: 首页 > 知识库问答 >
问题:

为什么clang拒绝可变模板friend函数

蒋飞捷
2023-03-14

我有以下示例代码,简化为基本代码,它使用GCC6.1、GCC7.0head和Visual Studio 2015/2017 RC编译,但不使用任何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:error:'_p'是'outer::foo'返回std::make_tuple(c_p...)的私有成员;

共有1个答案

阎唯
2023-03-14

在我看来,这是一个clang++bug(确实_pprivate,但是bar_()应该是foo类的friend函数)。

解决办法是在foo添加gettergetp()

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()...);
}
 类似资料:
  • 我有一个全局函数是这样的: 然后在另一个类中,我要将这个函数声明为的朋友。所以我做了: 现在,当我调用时,它无法编译,错误是foo无法访问的私有构造函数。我无法理解该错误,如何正确声明为的朋友? 提前道谢。

  • 我有一个将类型与整数值相关联的trait类。 我正在编写一个模板函数,返回类型由上面的traits类提供,并将其专门化为各种int值: 这可以与VS2015一起编译(参见https://godbolt.org/z/LpZnni)但VS2017并没有抱怨: 错误C2912:显式专门化的int函数 令我惊讶的是,像下面这样声明一个非模板函数会编译: 将公开可以解决编译问题,但我不明白为什么。对我来说,

  • 我正在学习一个视频教程,我想声明一个模板函数作为模板类的朋友。我不知道为什么代码会抛出错误。 编译器抛出错误。 错误: templates\u friends\u 38。cpp:在“void doSomething2(T)[T=int]”的实例化中:templates\u friends\u 38。cpp:40:19:此处需要templates\u friends\u 38。cpp:32:9:错误

  • 在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty

  • 我很好奇std::is_invocable_r的定义,以及它如何与不可移动类型交互。基于我对它应该模仿的语言规则的理解,它在C 20模式下的clang下的libc实现似乎是错误的,所以我想知道我的理解有什么不正确之处。 假设我们有一个不能移动或复制构造的类型,以及一个返回它的函数: 然后可以调用该函数来初始化对象(我认为是由于复制省略规则): 类型特征同意函数是可调用的,并返回: 但是,表示,调用

  • 我试图理解下面代码中的编译器错误。我有一个variadic模板函数,它接受具有指定类型的lambda,试图调用该函数会导致模板由于不匹配而不被视为有效的候选模板。 如果我将声明更改为不变: 然后它为上面的玩具示例工作,但对于真正的问题,我需要任意的论点。我是不是缺少了什么,或者还有什么方法可以做到这一点? 编辑:这被错误地标记为重复,我相信--受骗者没有回答我所问的问题。这个问题特别与这里的var