Я столкнулся с той же проблемой в моем собственном коде. Минимальный код, к которому я его сводил, был такой:
namespace N
{
template<typename T>
T defaultValue()
{
return T();
}
template<typename T>
void fun( const T& value = N::defaultValue<T>() ){}
}
int main(int argc, char* argv[])
{
N::fun<int>();
return 0;
}
Это немного отличается от примера Джеймса Макнеллиса - и, я думаю, подчеркивает тот факт, что это квалификация пространства имен в инициализаторе аргументов по умолчанию, где он идет не так.
В этом случае defaultValue и fun находятся в одном и том же пространстве имен, поэтому вы можете тривиально удалить N :: из N :: defaultValue, и это работает.
Если defaultValue находится в другом пространстве имен, вы все равно можете обойти его, перенеся его в локальное пространство имен с помощью или написав функцию шаблона локальной переадресации, например ::
namespace N1
{
template<typename T>
T defaultValue()
{
return T();
}
}
namespace N2
{
template<typename T>
T defaultValueFwd()
{
return N1::defaultValue<T>();
}
template<typename T>
void fun( const T& value = defaultValueFwd<T>() ){}
}
int main(int argc, char* argv[])
{
N2::fun<int>();
return 0;
}
Немного боли, но выполнимо. Я полагаю, что вы могли бы использовать эту технику в случае с make_shared, хотя я еще не пробовал.