2017-09-14 29 views
7

Próba utworzenia aliasu make_shared dla określonego typu klasy dla określonego konstruktora tej klasy. Moja najlepsza próba:Algorytm Constexpr funkcji przeciążonego szablonu

class foo { public: foo(int x) : y(x) {} int y; }; 
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>); 

Plony:

error: invalid static_cast from type ‘<unresolved overloaded function type>’ to type ‘std::shared_ptr<foo> (*)(int)’ 
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>); 

Co robię źle?

Odpowiedz

4

std::make_shared jest szablonem funkcji wariancji . Jako parametr szablonu podajesz tylko <foo>, ale potrzebujesz też gdzieś tam int. Bez względu na to, twoje podejście musi zakończyć się niepowodzeniem, ponieważ zależy od tego, jak argumenty szablonu zostały przedstawione i dlatego, że praca z zestawami przeciążeniowymi w C++ jest na ogół uciążliwa.

Co proponuję jest utworzyć funkcję otoki Zamiast:

constexpr auto newfoo(int x) 
{ 
    return std::make_shared<foo>(x); 
} 

Moim zdaniem łatwiej jest pisać, czytać i rozumieć. Jeśli naprawdę trzeba SFINAE obsługi oraz noexcept, można repeat the body three times:

constexpr auto newfoo(int x) 
    ->   decltype(std::make_shared<foo>(x)) 
     noexcept(noexcept(std::make_shared<foo>(x))) 
     {   return std::make_shared<foo>(x); } 

Makro może zostać wykorzystane do powyższego zgłoszenia mniej bolesne.


Jeśli naprawdę chcesz wskaźnik funkcji, to wydaje się działać:

auto newfoo = 
    static_cast<std::shared_ptr<foo>(*)(const int&)>(
     &std::make_shared<foo, const int&>); 

Spójrz na make_shared „deklarację:

template< class T, class... Args > 
shared_ptr<T> make_shared(Args&&... args); 

Trzeba podać T=foo i coś dla Args... . Ponieważ Args... jest paczką referencyjną do przekazywania, zawsze będzie ona wydedukować wartości wartości odniesienia lub wartości rvalue. Dlatego właśnie <foo, const int&> jest prawidłowym zbiorem parametrów szablonu, a <foo, int> nie jest.

Jak Zefick zauważył w komentarzach, wszystko to można uprościć do:

constexpr auto newfoo = &std::make_shared<foo, const int&>; 

Obsada nie jest naprawdę potrzebne tutaj.

+1

+1, ale prawdopodobnie powinieneś użyć 'const int &' zamiast 'int &&' w swoim przykładzie "jeśli naprawdę chcesz". Jak to jest, 'const int i = 42; auto f = newfoo (i); 'nie zadziała. –

+0

@MilesBudnek: dobry punkt, zmieniono moją odpowiedź –

+2

'constexpr auto newfoo = std :: make_shared ' po prostu działa. Dlaczego potrzebujemy obsady? – Zefick