C++: Correct syntax for friending a template type member of template parameter?

被刻印的时光 ゝ 提交于 2020-01-03 08:27:10

问题


I have a class that takes a template type parameter (tTRAIT). I want to friend a template type member alias of tTRAIT, but I can't figure out the syntax. (Is this even possible?).

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's error (on the friend line) is:

error: friend type templates must use an elaborated type

I have tried exhausting all possible combinations I can think of:

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>;

I have also tried using using, but it doesn't seem to help.

As an ugly hack (which only works for bool parameters), I can get it to work by friending each specialization manually.

friend typename tTRAIT::template TFoo<false>;
friend typename tTRAIT::template TFoo<true >;

But that's yucky.

Does anyone know how to do this, or if this can be done?


回答1:


I don't think this is possible. From standard draft N4296:

§ 14.5.4/1 [temp.friend]

A friend of a class or class template can be a function template or class template, a specialization of a function template or class template, or a non-template function or class.

This doesn't include alias templates, so the standard doesn't support what you want to do. This is perhaps due to the following excerpt (emphasis mine):

§ 14.5.7/1 [temp.alias]

A template-declaration in which the declaration is an alias-declaration (Clause 7) declares the identifier to be a alias template. An alias template is a name for a family of types.

An alias template names a separate family of types, so even if there were some syntax which made sense for this, you would be friending the alias template rather than the template which is being aliased.

For example, GCC will compile this (Clang won't), but you won't actually be able to use the friendship in any reasonable way:

template <bool B>
using MyTFoo = typename tTRAIT::template TFoo<B>;

template <bool> friend class MyTFoo; 

Another example of how an alias template is not the same as the aliased template:

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");

Your manual friending with explicit instantiation will work, because the alias template will collapse down to exactly the same type as the aliased template. An analogous example:

//this passes!
static_assert(std::is_same<myvec<int>,std::vector<int>>::value, "wat");



回答2:


I could go I step further with Clang 3.4.1 in std=c++11 mode.

This compiles without error :

template

struct SBar
    {
private:
    int j;
public:
        template <bool bBOOL>
        friend struct tTRAIT::TFoo;
        void setJ(int j) {
            this->j = j;
        }
};

But ... I get this warning : warning: dependent nested name specifier 'tTRAIT::' for friend template declaration is not supported; ignoring this friend declaration [-Wunsupported-friend] : friend struct tTRAIT::TFoo;

and I can confirm that the SFoo classes are not friend (the reason for private j ...)

The only way I could have it all to compile and run is :

struct SBar
    {
private:
    int j;
public:
        template <bool bBOOL>
        friend struct sFoo;
        void setJ(int j) {
            this->j = j;
        }
};

Fine, SFoo classes are friends, but it somewhat defeats OP requirement ( template type member of [template parameter]) ...

I currently have no access to a recent gcc but I think we are here on the edge of how compilers interprets the standard. I read the chapter referenced by TartanLlama, but could not make sure if this was intended or not. Maybe my first try would be accepted by gcc ...



来源:https://stackoverflow.com/questions/29945432/c-correct-syntax-for-friending-a-template-type-member-of-template-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!