Indeed, this seems like a mistake. A workaround is to split the default template parameter into a second function. Inside clone_ptr you have two friends:
template<class T1, typename ...Args> friend clone_ptr<T1> make_cloned( Args ...args ); template<class T1, class U1, typename ...Args> friend clone_ptr<T1> make_cloned( Args ...args );
and the definition is easy:
template<typename T, typename ...Args> clone_ptr<T> make_cloned( Args ...args ) { return {new T(args...)}; } template<typename T, typename U, typename ...Args> clone_ptr<T> make_cloned( Args ...args ) { return {new U(args...)}; }
Tested with gcc 4.8.3 and clang 3.5.
Edit: After learning, I was able to get your code working with gcc 4.8.3 in two different ways:
Delete the declaration of the template function completely
// this is not needed: template<typename T, typename U, typename ...Args> clone_ptr<T> make_cloned( Args ...args );
Move the default template parameter definition from the template function definition to the declaration:
template<typename T, typename U = T, typename ...Args> clone_ptr<T> make_cloned( Args ...args ); template<typename T, typename U, typename ...Args> clone_ptr<T> make_cloned( Args ...args ) { return {new U(args...)}; }
I still assume this is a problem with gcc, but this way your code works.
jepio source share