为什么我不能通过模板参数声明友元函数类型,但是可以使用别名?

3

考虑以下代码:

template <class T>
class Bar {
    int foobar;
    using X = T();
    friend X foo;
};

void foo() {
    Bar<void> bar;
    bar.foobar = 1;
    static_cast<void>(bar);
}

int main() {}

gccclang中编译都没问题。但是,看起来等效的代码:

template <class T>
class Bar {
    int foobar;
    friend T foo;
};

void foo() {
    Bar<void()> bar;
    bar.foobar = 1;
    static_cast<void>(bar);
}

int main() {}

gccclang中都会引发错误。为什么模板参数在这里不能像别名一样正常工作?


我花了一点时间才注意到你在一个参数里发送了 void,而在另一个参数里发送了 void() - StoryTeller - Unslander Monica
1
“崩溃”通常不意味着你现在所使用的含义。 - T.C.
3
并且,https://timsong-cpp.github.io/cppwp/temp#spec-7 - T.C.
@T.C. 抱歉 - 正在编辑。 - W.F.
嗯...我想T.C.解决了这个问题... - StoryTeller - Unslander Monica
没错,那很快。@T.C. 谢谢! - W.F.
1个回答

1
因为T foo被解析为对象的声明,而模板实例化不能将对象的声明更改为函数的声明。
C++标准/[temp.spec]:

如果一个函数声明通过依赖类型(17.7.2.1)获得其函数类型,而没有使用函数声明符的语法形式,则程序是非法的。


是的,虽然有点奇怪,因为你不能将一个对象声明为友元,但我认为这是潜在的原因。谢谢! - W.F.
确实很奇怪。实际上编译器知道 friend 不能是一个对象,因为对象声明不能转换为函数声明,它们会在任何实例化之前预先检测到问题并报告错误。 - Oliv

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