与模板模板参数交朋友

30

我有一个带有模板模板参数的类模板,我想将此参数(即其所有特化)声明为friend。但是我找不到正确的语法。

template <template <class> class T>
struct Foo {

    template <class U>
    friend T;           // "C++ requires a type specifier for all declarations"

    template <class U>
    friend struct T;    // "declaration of 'T' shadows template parameter"

    template <class U>
    friend struct T<U>; // "cannot specialize a template template parameter"

    pretty<please>
    lets(be) friends T; // Compiler shook its standard output in pity
};

如何将模板模板参数声明为friend

Coliru代码片段


1
我没有答案,但是这里有一些参考资料:CWG585 - 被认为不是一个缺陷,尽管我真的不知道它所谓的合理性是什么意思。还有,这个GCC补丁; GCC确实接受template<class> friend class T;,而Clang和EDG则会拒绝(MSVC并不会直接拒绝,但似乎也不会对其进行任何有用的操作)。 - bogdan
6
我不确定你想要表达什么,但也许这个可以起作用?template <class U, template<class> class T> struct Foo { friend T<U>; }; (翻译者注:该代码片段为 C++ 代码,意思是定义一个名为 Foo 的数据结构,其中包含一个友元函数模板,该函数模板接受一个类型参数 U 和一个模板参数 T,并将 T 应用于 U。) - Michael Nastenko
3
确实,我同意当前措辞下该形式无效(根据[temp.class.spec]/1,T<U>是一个偏特化,尽管它是无效的,因为它没有比主模板更加特化)。我期望正确的形式要么是你示例中的第一个,要么就像CWG585提案的解决方案那样简单明了,即friend T;,以保持与非模板模板参数的一致性。看起来严格标准术语来说现在有些混乱。 - bogdan
1
我本来想说“让我们在std-discussion上问一下”,但是Brian Bi已经这样做了,并引用了你的问题,所以让我们看看那个帖子的进展如何。 - bogdan
7
请问有人能够提交 pretty<please> lets(be) friends T; 的语法以供标准批准。 - sp2danny
显示剩余4条评论
2个回答

2

我发现这个问题很有研究价值。根据标准(C++11及以上版本),这应该是可以正常工作的,我想:

template <template <class> class U>
struct identity {
    template <typename T>
    using type = U<T>;
};

template <template <class> class U>
struct Foo {
    template <typename>
    friend class identity<U>::type;
};

由于只有一个间接级别,这里没有任何阴影和名称重用,这种情况描述如下:

cppreference

函数模板和类模板声明都可以出现在任何非局部类或类模板中的友元说明符中(...)。在这种情况下,模板的每个特化都成为友元,无论它是隐式实例化、部分特化还是显式特化。例如:class A { template<typename> friend class B; }

然而,似乎clang和MSVC持不同看法:请参见colirugodbolt。此外,它们的错误消息似乎毫无意义,因此看起来像是编译器bug(或者只是错误地检测到语法错误)。GCC完美地编译和执行了上述片段,但我仍然不确定这是否是正确的解决方案。

哇,这看起来非常奇怪——我不知道模板参数推导和友元声明如何交互,但我很惊讶这可以通过非推导上下文工作。尽管如此,这看起来像是有价值的信息 :) - Quentin

-2

模板往往会让程序员过度复杂化事情。我不确定你想做什么,而且我认为可能有更好的方法来完成它,但这应该可以工作。

template <template <class> class T, class U>
class Foo {
    friend class T<U>;
};

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