problem with `candidate template ignored: invalid explicitly-specified argument'

Folks,

below is a MWE that compiles fine with g++ but fails with clang
(tested version 6.0.1 on a GNU/Linux box):

  clang-problem.cpp:19:7: error:
      no matching member function for call to 'zip'
    bex.zip <&B::fun> ();
    ~~~~^~~~~~~~~~~~~
  clang-problem.cpp:13:8: note: candidate template ignored:
      invalid explicitly-specified argument for template parameter 'mf'
    void zip () { }
         ^

To my best knowledge, the code is valid C++. This means there are two
possible corrolaries: either I'm wrong, and it is not valid C++
according to the standard, or clang++ has a bug. Hopefully, it's the
former.

Can you point out a solution?

    Werner

Yeah, looks like a bug in Clang to me - CC’ing Richard Smith in case this is quick/easy/obvious to him. Here’s my slightly modified test case comparing Clang and GCC’s behavior, and adding a non-member overload situation to demonstrate that that works on both compilers: https://godbolt.org/z/cTq06R

I minimized the reproducer. Seems like base class template methods are not included in derived object method name resolution.

Knowing whether it violates the standard or not is beyond my knowledge though.

type params
https://godbolt.org/z/WpET78

nontype params
https://godbolt.org/z/PZIaDn

Jan

Ah, good point - I didn’t think to simplify the template argument list/types too!

Yeah, looks like a bug in Clang to me - CC'ing Richard Smith in case
this is quick/easy/obvious to him.

Thanks to all for checking! Shall I open an issue for clang?

    Werner

Sure, that’d be great - http://bugs.llvm.org

Sure, that'd be great - http://bugs.llvm.org

Done:

  39581 – base class template methods are not included in derived object method name resolution

    Werner

The rule for determining when a base class function declaration introduced by a using-declaartion is hidden by a derived class function declaration does not take the template parameter list into account: http://eel.is/c++draft/namespace.udecl#15.sentence-1

So clang’s behaviour is conforming and gcc’s behaviour is not. At the very least, though, we should issue a warning for the using declaration, because this is a surprising rule.

The rule for determining when a base class function declaration
introduced by a using-declaration is hidden by a derived class
function declaration does not take the template parameter list into
account: [namespace.udecl]

Our main lilypond developer disagrees. He writes:

  This link states:

    When a using-declarator brings declarations from a base class into
    a derived class, member functions and member function templates in
    the derived class override and/or hide member functions and member
    function templates with the same name, parameter-type-list,
    cv-qualification, and ref-qualifier (if any) in a base class
    (rather than conflicting).

  The parameter-type-list is a different one in this example since
  they contain a different member function pointer type. Which is the
  reason we need the whole hooplahoop in the first place.

For context, the whole lilypond thread starts at

  compilation with clang

    Werner

The rule for determining when a base class function declaration
introduced by a using-declaration is hidden by a derived class
function declaration does not take the template parameter list into
account: [namespace.udecl]

Our main lilypond developer disagrees. He writes:

This link states:

   When a using-declarator brings declarations from a base class into
   a derived class, member functions and member function templates in
   the derived class override and/or hide member functions and member
   function templates with the same name, parameter-type-list,
   cv-qualification, and ref-qualifier (if any) in a base class
   (rather than conflicting).

The parameter-type-list is a different one in this example since
they contain a different member function pointer type. Which is the
reason we need the whole hooplahoop in the first place.

Isn’t it template-parameter-list that is different rather than parameter-type-list?

http://eel.is/c++draft/dcl.fct#def:parameter-type-list
http://eel.is/c++draft/temp#nt:template-parameter-list

The rule for determining when a base class function declaration
introduced by a using-declaration is hidden by a derived class
function declaration does not take the template parameter list into
account: http://eel.is/c++draft/namespace.udecl#15.sentence-1

Our main lilypond developer disagrees. He writes:

This link states:

When a using-declarator brings declarations from a base class into
a derived class, member functions and member function templates in
the derived class override and/or hide member functions and member
function templates with the same name, parameter-type-list,
cv-qualification, and ref-qualifier (if any) in a base class
(rather than conflicting).

The parameter-type-list is a different one in this example since
they contain a different member function pointer type. Which is the
reason we need the whole hooplahoop in the first place.

Isn’t it template-parameter-list that is different rather than parameter-type-list?

http://eel.is/c++draft/dcl.fct#def:parameter-type-list
http://eel.is/c++draft/temp#nt:template-parameter-list

Yes. The pieces are these:

template
// template-parameter-list
void f
(int N) // parameter-type-list

Both base and derived function template have a parameter-type-list of (). :frowning:

Yes. The pieces are these:

template
  <typename T> // template-parameter-list
void f
  (int N) // parameter-type-list

Both base and derived function template have a parameter-type-list
of (). :frowning:

Thanks for the analysis. I now wonder whether there is a work-around
to make the code work with clang also. Any ideas?

    Werner