[cfe-dev] clang c++0x template function declaration error

Seth Cantrell seth.cantrell at gmail.com
Sat Jul 16 20:04:13 PDT 2011

On Jul 16, 2011, at 2:45 PM, John McCall wrote:

> On Jul 16, 2011, at 9:31 AM, Seth Cantrell wrote:
>> Could the diagnostics be improved over
>>> test.cpp:4:6: note: candidate template ignored: substitution failure
>>>     [with T = Y]
>>> auto type_constructor( void (T::*f)() ) -> X< T, f >;
>>>    ^
>> ?
>> Maybe an added note that points at the f in X<T,f> to say that that's why the substitution failed?
> While I agree that 'substitution failure' by itself is not very helpful, I'm very reluctant to use multiple notes per failed overload candidate, at least for the default console diagnostics.  Is there a good way to explain the problem based on the kind of substitution failure?

Okay, I think not multiplying notes that way is good. Thinking about it more, it seems like this shouldn't even be a note attached to an error because I don't think there's any way the template could ever be instantiated. Instead as soon as clang sees:

> template <class T> 
> auto type_constructor( void (T::*f)() ) -> X< T, f >;

it seems like it should pop out an error declaring that the template is invalid (and explaining why by stating that the function's parameter 'f' can't be used as a non-type template parameter in X<T,f>). I'm not exactly sure what the restrictions are on what values can be used as non-type template parameters, but it's obvious that the value has to be available at compile time.

So later on, when the code tries to use this template the note can say something like this:

> test.cpp:4:6: note: candidate template ignored: invalid template
> template<typename T> auto type_constructor( void (T::*f)() ) -> X< T, f >;

>> Here's an example of a similar mistake:
>>> #include <functional>
>>> template<typename T>
>>> void get(T const &t,size_t N) {
>>>   std::get<N>(t);
>>> }
>>> int main () {
>>>   get(std::make_tuple(1,'a',1.2),2);
>>> }
>> When compiling this the diagnostics include several notes like the following
>>> /usr/include/c++/v1/__tuple:104:1: note: candidate template ignored: invalid explicitly-specified
>>>     argument for template parameter '_Ip'
>>> get(array<_Tp, _Size>&) _NOEXCEPT;
>> "invalid explicitly-specified argument for template parameter" is a little better but it'd be nice to see something pointing directly at the 'N' in std::get<N>(t) saying it's not legal to use arguments as template parameters. Would this be hard to add? Maybe I can give it a try.
> Again, we'd rather not introduce extra notes, but it would be fine to just specialize this note for common problems.  For example, here you could say:
>  note: candidate template ignored: explicit argument for template parameter '_lp' is not a type
> or maybe even
>  note: candidate template ignored: explicit argument 'N' for template parameter '_lp' is not a type
> where N is a string derived from pretty-printing the argument expression.
> John.

Similarly, instead of attaching extra notes to the error clang should be able to recognize that this case is an invalid use of a non-type template parameter. This way there wouldn't even be a reason to look at any candidate templates and all of the (possibly many) notes about failed candidate templates can be eliminated. All the developer needs to know is that you can't pass runtime values to template parameters, and clang can point him directly at the spot where he's trying to do that.

> test.cpp:5:5: error: cannot instantiate templates using function parameter values.
>     std::get<N>(t);
>              ^
> test.cpp:4:28: note: 'N' declared here
> void get(T const &t,size_t N) {
>                     ^~~~~~~~

More information about the cfe-dev mailing list