Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are reference non-type template parameters deduced by decltype(auto) forwardable in case of template template parameter

Yet another decltype(auto) template template-parameter question. This time minimal code I was able to create to reproduce the error looks like this:

template <template <decltype(auto)> class TT, decltype(auto) V>
void foo(TT<V>) {
};

template <decltype(auto)>
struct Bar{};

int x;

int main() {
    foo(Bar<(x)>{});
}

This in [clang] results in:

prog.cc:11:5: error: no matching function for call to 'foo'
    foo(Bar<(x)>{});
    ^~~
prog.cc:2:6: note: candidate template ignored: substitution failure [with TT = Bar]: non-type template argument is not a constant expression
void foo(TT<V>) {
     ^
1 error generated.

[gcc] accepts the code.

To my understanding the code is well-formed and clang is buggy in its interpretation, but need the confirmation before submitting a bug to lvvm. Am I right?

like image 571
W.F. Avatar asked Sep 20 '17 17:09

W.F.


People also ask

What does Decltype auto do?

Use auto and decltype to declare a function template whose return type depends on the types of its template arguments. Or, use auto and decltype to declare a function template that wraps a call to another function, and then returns the return type of the wrapped function.

Which of the following can be passed by non-type template parameters during compile time?

What can be passed by non-type template parameters during compile time? Explanation: Non-type template parameters provide the ability to pass a constant expression at compile time. The constant expression may also be an address of a function, object or static class member.

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

What is template argument deduction?

Template argument deduction is used in declarations of functions, when deducing the meaning of the auto specifier in the function's return type, from the return statement.


1 Answers

According to error clang does not have a problem with deducing template template-parameter which is also standard compliant - [temp.arg.template]/3 (empasis mine):

A template-argument matches a template template-parameter P when P is at least as specialized as the template-argument A. If P contains a parameter pack, then A also matches P if each of A's template parameters matches the corresponding template parameter in the template-parameter-list of P. Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent ([temp.over.link]), and for template template-parameters, each of their corresponding template-parameters matches, recursively. When P's template-parameter-list contains a template parameter pack, the template parameter pack will match zero or more template parameters or template parameter packs in the template-parameter-list of A with the same type and form as the template parameter pack in P (ignoring whether those template parameters are template parameter packs)

Now lets make sure the Bar<(x)>{} should be deduced as reference. This is covered by [dcl.type.auto.deduct]/5 and [dcl.type.simple]/4.

Finally lets check if we actually can use the reference to the variable with linkage as a template argument [temp.arg.nontype]/2:

A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

  • a subobject,
  • a temporary object,
  • a string literal,
  • the result of a typeid expression, or
  • a predefined ­­func_­_­ variable.

[ Note: If the template-argument represents a set of overloaded functions (or a pointer or member pointer to such), the matching function is selected from the set ([over.over]). — end note  ]

The deduced argument fulfils the requirements. This makes the code well-formed and suggests clang's bug.

Filed bug 34690

like image 119
W.F. Avatar answered Oct 26 '22 23:10

W.F.