Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template member of a non-template class as a friend

The following snippet is compiled fine by gcc, icc and msvc (latest question), but trips clang with <source>:6:9: error: calling a private constructor of class 'B<int>' in the marked line. Yet it works fine for the free template function, as shown in the code:

struct A {
    template<class T>
    static void create () {
        T();
    }
};

template<class T>
void create() {
    T();
}

template<typename T>
struct B {

    friend void A::create<B>();
    friend void create<B>();

    private:
    B() = default;
};

int main() {
     A::create<B<int>>(); // clang trips here
     create<B<int>>(); // fine!
}

What might be the difference between a static template member of non-template class and free template function in this context?

like image 249
SergeyA Avatar asked May 25 '18 14:05

SergeyA


People also ask

Can a template class be a friend?

Many-to-one: All instantiations of a template function may be friends to a regular non-template class. One-to-one: A template function instantiated with one set of template arguments may be a friend to one template class instantiated with the same set of template arguments.

Can a non templated class have a templated member function?

A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.

Can member functions be declared as template?

Member functions can be function templates in several contexts. All functions of class templates are generic but are not referred to as member templates or member function templates. If these member functions take their own template arguments, they are considered to be member function templates.

Can you inherit template class?

It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.


1 Answers

I found a bug reported for Clang, "Access to a public template alias declaration that refers to friend's private nested type is not allowed" which seems similar to this issue as it relates to a friend (template within a structure as in the OP) accessing a private member of a class.

The failed test case is:

struct FooAccessor
{
    template <typename T>
    using Foo = typename T::Foo;
};

class Type
{
    friend struct FooAccessor;        
    using Foo = int;
};

int main()
{
    FooAccessor::Foo<Type> t;
}

The result is:

$ clang++ test.cpp -std=c++11
test.cpp:4:5: error: 'Foo' is a private member of 'Type'
    using Foo = typename T::Foo;
    ^
test.cpp:11:11: note: implicitly declared private here
    using Foo = int;
          ^
1 error generated.
like image 115
P.W Avatar answered Sep 17 '22 01:09

P.W