15

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?

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • 2
    I have no idea what I'm talking about but since last year I think, clang has had problems with `friend`s with templates - see how libstdc++'s `std::variant` doesn't work under clang. Pretty sure this is the same or similar problem. – Rakete1111 May 25 '18 at 14:30
  • @Rakete1111 do you have any links to bug reports, tickets raised, etc? – SergeyA May 25 '18 at 14:32
  • 4
    [pr33322](https://bugs.llvm.org/show_bug.cgi?id=33222) and another one I can't find currently. – Rakete1111 May 25 '18 at 14:34
  • 1
    @Rakete1111 interesting, thanks. A showstopper bug which is open for almost a year... – SergeyA May 25 '18 at 14:35
  • @Rakete1111 An answer like "It's a bug in clang - see these bug reports" would be good. – Martin Bonner supports Monica May 25 '18 at 14:44
  • 3
    @MartinBonner I'm not actually sure that this bug is related. For all I know gcc, icc and msvc are all wrong, I just have no idea which is why I didn't post it as an answer. – Rakete1111 May 25 '18 at 14:45

1 Answers1

1

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.
P.W
  • 26,289
  • 6
  • 39
  • 76
  • If this is not the same issue, please let me know and I will delete the answer. – P.W Feb 01 '19 at 06:09