2010-05-07 3 views
4

В Visual C++ (2008 и 2010), следующий код не компилируется со следующей ошибкой:станд :: make_shared в качестве аргумента по умолчанию не компилируется

#include <memory> 

void Foo(std::shared_ptr<int> test = ::std::make_shared<int>(5)) 
{ 
} 

class P 
{ 
    void 
    Foo(std::shared_ptr<int> test = ::std::make_shared<int>(5)) 
    { 
    } 
}; 

ошибка C2039: «make_shared»: не членом '' глобального пространства имен'»

ошибка C3861: '' make_shared: идентификатор не найден

Он жалуется на определение P :: Foo() не :: Foo().

Кто-нибудь знает, почему это действительно для Foo(), чтобы иметь аргумент по умолчанию с std :: make_shared, но не P :: Foo()?

+0

Обратите внимание, что в Visual C++ 2008 'shared_ptr' находится в' std :: tr1', а 'make_shared' не реализован (' make_shared' не был частью TR1). –

+0

звучит так, как будто вы делаете ':: make_shared' –

+0

Игнорируйте бит 2008 года, я запутал IDE с компилятором. –

ответ

6

Это похоже на ошибку в компиляторе. Вот минимальный код, необходимый для воспроизведения проблемы:

namespace ns 
{ 
    template <typename T> 
    class test 
    { 
    }; 

    template <typename T> 
    test<T> func() 
    { 
     return test<T>(); 
    } 
} 

// Works: 
void f(ns::test<int> = ns::func<int>()) { } 

class test2 
{ 
    // Doesn't work: 
    void g(ns::test<int> = ns::func<int>()) 
    { 
    } 
}; 

Visual C++ 2008 и 2010, как сообщают:

error C2783: ' ns::test<T> ns::func(void) ' : could not deduce template argument for ' T '

Комео не имеет никаких проблем с этим кодом.

+1

Я отправил отчет о дефектах в Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/557653 –

0

Я попал в ту же проблему, что и в моем собственном коде. Минимальный код, который я варил вниз был таков:

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; 
} 

Это немного отличается, например Джеймс McNellis - и, я думаю, подчеркивает тот факт, что она является квалификация имен в аргументе по умолчанию initiliser, где идет не так ,

В этом случае 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, хотя я этого не пробовал.

Смежные вопросы