一个在类中定义的友元函数模板是否可供查找?Clang++和G++存在分歧。

10

以下是代码:

struct foo {
  template<typename T = void>
  friend foo f() { return {}; }
};

int main() {
  auto x = f(); // clang++ can't find it, g++ can.
}

clang++ 3.4 的输出:

fni2.cpp:8:12: error: use of undeclared identifier 'f'
  auto x = f(); // clang++ can't find it, g++ can.
           ^
1 error generated.

g++ 4.9.0编译了它,但我认为它不应该这样做。这个问题是相关的,但没有明确的答案。第15.4.2/2,4节讨论了这个问题,但它们都没有表明在类中定义的友元函数模板应该与在类中定义的非模板友元函数有不同的可见性。

这只是我的学术兴趣,但它是由另一个人的问题引起的,这个人可能有一个实际的用例。

在我看来这似乎是g++的一个bug。


看起来 g++ 有问题,关于内联友元函数的作用域,请参考此链接:https://dev59.com/Q2sy5IYBdhLWcg3w9Srk - yngccc
是的,我也认为g++是错的。只是想看看是否有其他人与我在标准中阅读这些段落的方式不同,或者是否有我错过的标准段落。 - kec
我看到有些人使用这种方法将方法替换为函数。他们使用类作为作用域。 - yngccc
@yngum 这是一个有效的技巧,但你必须在class定义之外重新声明函数[template]。(更好的风格是使用namespaceusing声明。) - Potatoswatter
@yngum:这样做的动机是什么?为什么不使用命名空间?我想到的一个可能性是利用部分特化。 - kec
@kec 我看不出有什么理由,这主要是一种风格,有些人喜欢将数据和函数打包在一起。我通常只是在结构体后面声明函数而不使用命名空间,我不喜欢方法。 - yngccc
1个回答

7

是的,这是一个错误。我很惊讶它能找到这个函数。显然,GCC完全没有隐藏函数模板。

这个C++03的例子也可以编译,所以可能是一个回归问题:

struct foo {
  template<typename T >
  friend void f( T ) { }

};

int main() {
  f( 3 ); // clang++ can't find it, g++ can.
}

如果没有默认的模板参数,它似乎也是有问题的。(我会编辑以使其清晰明了。)如果不是一个模板,那么g++无法按预期找到它。 - kec
@user3521733 不用担心,我已经尝试过并更新了答案。 - Potatoswatter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接