c++gcccompiler-errorsg++clang

Binding to initializer_list accepted by g++, but rejected by clang


The following code is accepted by g++ (14.2.1):

#include <vector>

template<typename T>
void foo(T i, std::vector<int> &v = {})
{  }

int main()
{
    std::vector<int> v;
    foo(3, v);
}

but rejected by clang (19.1.7) with:

non-const lvalue reference to type 'std::vector<int>' cannot bind to an initializer list temporary

If I rely on the default argument (by omitting the 2nd parameter), both compilers reject the code, which makes sense since an attempt is made to bind a non-const lvalue reference to an rvalue.

Is clang correct by rejecting the code or is g++ correct by accepting the code?


Solution

  • Default arguments of function templates are not instantiated until used by a call expression ([temp.inst]/12). In your case there is no use of the default argument since when you call foo, you explicitly provide a second argument.

    Because this default argument can never be valid, a compiler is permitted, but not required, to diagnose it when it is not instantiated ([temp.res.general]/6.1).

    Note that we have some weasel wording in the standard that says that default arguments are considered as independent definitions in some sense ([temp.decls.general]/3), which is intended to allow rules like the above to apply to them.