Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static private function with templated type as a default argument in C++

I have the following piece of C++17 code:

template <typename Callback = void(*)()>
struct A {
    A(Callback c = &noop) {}
private:
    static void noop() {}
};

int main() {
    A a{};
}

Clang 6 compiles this without any errors, but GCC 8.2 says:

In function ‘A(Callback)-> A<Callback> [with Callback = void (*)()]’:
3:24: error: ‘static void A<Callback>::noop() [with Callback = void (*)()]’ is private within this context
  A(Callback c = &noop) {}
                 ^~~~~
5:14: note: declared private here
  static void noop() {}
              ^~~~

Interestingly, if Callback is not a template argument but a simple type alias (i.e. if I write using Callback = void (*)() inside of the A class), both compilers are fine. Also, if instead of A a{}; I explicitly write A<> a{};, both compilers are again fine. This leads me to think that this problem is somehow connected to the new C++17 class template deduction mechanism.

My question is, which of the compilers is right according to the standard? Is this a GCC bug or is Clang being too permissive?

like image 881
Nikola Benes Avatar asked Aug 08 '18 14:08

Nikola Benes


1 Answers

CTAD notionally proceeds by synthesizing a set of functions and function templates ([over.match.class.deduct]p1). As relevant here, the set includes :

If C is defined, for each constructor of C, a function template with the following properties:

  • The template parameters are the template parameters of C followed by the template parameters (including default template arguments) of the constructor, if any.
  • The types of the function parameters are those of the constructor.
  • The return type is the class template specialization designated by C and template arguments corresponding to the template parameters of C.

Notably, this omits default function arguments. This is almost certainly a defect.

Unfortunately, this defect also means that nobody knows from the standard how access control works for the default function arguments of the synthesized function templates - it doesn't even permit them to exist in the first place.


From a design perspective, I'd expect Clang's behavior to be correct.

like image 159
T.C. Avatar answered Oct 17 '22 02:10

T.C.