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?
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.