【问题标题】:Template Default Arg Substitution failure in clang 3.3clang 3.3 中的模板默认参数替换失败
【发布时间】:2013-09-25 05:40:44
【问题描述】:

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

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 的私有,因此违反了私有成员 I 的访问规则(这是有效的)。 gcc 不会为函数 h 抛出错误,因为它已被声明为类 A 的朋友,因此可以访问私有成员 I。

Clang 对这两个函数都抛出错误。函数 j 的错误(未声明的朋友是有效的并且如预期的那样),但即使对于朋友函数 h 也会引发错误(错误:默认 arg 的推导失败,因为我是 A 类的私有成员)。这违反了朋友功能的可访问性。

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

【问题讨论】:

  • 好吧,我得到了一个与你不同的错误,但为什么使用依赖于第一个参数的默认参数(甚至不知道这是允许的)你可以稍后自己制作 typedef函数或类

标签: c++ clang


【解决方案1】:

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

这应该可以解决问题:

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

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

修复上述错误后,我仍然遇到错误,因为

  • 您在私有部分中声明了 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);
}

【讨论】:

  • @aaronman OP 用一个很好的例子写了很多东西,但是编译失败了。添加模板函数的返回类型解决了这个问题。还是我弄错了什么问题?
  • 谢谢。仅当我在公共部分中定义时才有效。虽然我想知道为什么它不适用于私有声明,因为友元函数也可以访问私有成员。
  • @sarda 我不认为模板参数是朋友声明的一部分。因此,他们看不到它。
猜你喜欢
  • 2019-07-31
  • 2013-06-20
  • 1970-01-01
  • 2015-07-12
  • 2018-04-28
  • 2019-09-11
  • 2014-09-22
  • 1970-01-01
  • 2019-06-18
相关资源
最近更新 更多