c++ - clang 3.3 中的模板默认 Arg 替换失败

标签 c++ clang

这是关于涉及默认参数的测试用例 扣除/替代。测试用例可以概括为:

template <class T, class = typename T::I>h(T){}

template <class T, class = typename T::I>j(T){}

class A
{
   typedef int I;
   friend void h<A>(A);

};

int main()
{
   A a;
   h(a);
   j(a);
}

gcc-4.8.1 为函数 j 抛出错误,因为它没有被声明为友元,也不是类 A 的私有(private)成员,因此违反了私有(private)成员 I(有效)的访问规则。 gcc 不会为函数 h 抛出错误,因为它已被声明为类 A 的友元,因此可以访问私有(private)成员 I。

Clang 会为这两个函数抛出错误。函数 j 的错误(未声明的 friend 是有效的并且符合预期),但它甚至对于 friend 函数 h 也会抛出错误(错误:默认 arg 的推导失败,因为我是类 A 的私有(private)成员)。这违反了好友功能的可访问性。

我检查了代码路径。虽然 clang 能够推断出默认参数,但它会在进行任何替换之前检查访问规则,并给出错误。有人可以就如何解决这个问题提供指导吗?

最佳答案

您忘记了模板函数的返回类型。

这应该可以解决问题:

template <class T, class = typename T::I> void h(T){}

template <class T, class = typename T::I> void j(T){}

修复了上面的错误后,还是报错,因为

  • 您在私有(private)部分声明了 typedef。你需要把它公开
  • 你错误地声明了函数 friend。它有两个模板参数(A::I 不会工作,因为 A 不是完整类型)

完全可编译的问题在这里:

#include <iostream>

// Type your code here, or load an example.
template <class T, class = typename T::I> void h(T t){std::cout<<t.a<<std::endl;}

template <class T, class = typename T::I> void j(T t){std::cout<<t.a<<std::endl;}

class A
{
   friend void h<A,int>(A);
   friend void j<A,int>(A);
public :
   typedef int I;
  private :
  int a;

};

int main()
{
   A a;
   h(a);
   j(a);
}

关于c++ - clang 3.3 中的模板默认 Arg 替换失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18997070/

相关文章:

c++ - 比较 int 的正向和反向循环,其中一个限制为 0

c++ - 这种优化是否是编译器错误?

c++ - 模板类静态成员的初始化

clang - 在 Travis CI 上为 C++17 设置 Clang

c - 使用标记为 __unused 的参数时发出警告

c++ - 用于静音未使用变量警告的跨平台宏

c++ - 为什么添加 constexpr 会使 VS2013 拒绝这个?

c++ - 有没有一种方法可以将std::string转换为c++中的vector <char>?

c++ - 多重继承指定所需的虚函数而不重新定义它

c++ - 带有 Boost 的 Node-gyp 包含和库目录