我有一个采用模板类型参数(tTRAIT)的类。我想和tTRAIT的模板类型成员别名成为 friend ,但是我无法弄清楚语法。 (这甚至可能吗?)。
template <bool bBOOL>
struct SFoo {};
struct STrait
{
template <bool bBOOL>
using TFoo = SFoo<bBOOL>;
};
template <typename tTRAIT>
struct SBar
{
template <bool bBOOL>
friend typename tTRAIT::template TFoo<bBOOL>;
};
SBar<STrait> bar;
Clang的错误(在
friend
行上)是:error: friend type templates must use an elaborated type
我已经尝试了所有可能想到的组合:
friend tTRAIT::TFoo;
friend tTRAIT::template TFoo;
friend typename tTRAIT::TFoo;
friend typename tTRAIT::template TFoo;
template <bool bBOOL> friend tTRAIT::TFoo;
template <bool bBOOL> friend tTRAIT::TFoo<bBOOL>;
template <bool bBOOL> friend tTRAIT::template TFoo;
template <bool bBOOL> friend tTRAIT::template TFoo<bBOOL>;
template <bool bBOOL> friend typename tTRAIT::TFoo;
template <bool bBOOL> friend typename tTRAIT::TFoo<bBOOL>;
template <bool bBOOL> friend typename tTRAIT::template TFoo;
template <bool bBOOL> friend typename tTRAIT::template TFoo<bBOOL>;
我也尝试过使用
using
,但这似乎没有帮助。作为一个丑陋的技巧(仅适用于 bool 参数),我可以通过手动将每个特化设置为好友来使其工作。
friend typename tTRAIT::template TFoo<false>;
friend typename tTRAIT::template TFoo<true >;
但这真令人讨厌。
有谁知道该怎么做,或者是否可以做到这一点?
最佳答案
我认为这是不可能的。根据标准草案N4296:
§14.5.4/1 [temp.friend]
这不包括别名模板,因此该标准不支持您要执行的操作。这可能是由于以下摘录(重点是我的):
§14.5.7/1 [temp.alias]
别名模板命名了一个单独的类型系列,因此,即使有一些对此有意义的语法,您也应该将别名模板而不是被别名的模板作为 friend 。
例如,GCC将编译此代码(Clang不会),但实际上您将无法以任何合理的方式使用友谊:
template <bool B>
using MyTFoo = typename tTRAIT::template TFoo<B>;
template <bool> friend class MyTFoo;
别名模板与别名模板不同的另一个示例:
template <template <typename...> class A, template <typename...> class B>
struct is_same_template : std::false_type{};
template <template <typename...> class A>
struct is_same_template<A,A> : std::true_type{};
template <typename T> using myvec = std::vector<T>;
//this fails
static_assert(is_same_template<myvec,std::vector>::value, "wat");
您可以手动使用显式实例化,因为别名模板将折叠为与别名模板完全相同的类型。一个类似的例子:
//this passes!
static_assert(std::is_same<myvec<int>,std::vector<int>>::value, "wat");