2013-04-26 15 views
5

Dlaczego jest tak, że to kompiluje:Dlaczego nie mogę szablonować przeciążenia?

class Testable { 
public: 
    template <bool flag> 
    typename std::enable_if<flag>::type 
    void foo() { cout << "Yay" << endl; } 

    template <bool flag> 
    typename std::enable_if<!flag>::type 
    void foo() { cout << "Nay" << endl; } 
}; 

Ale jeśli nie mogę zdefiniować zarówno Foos Używanie typów domyślnych tak:

template <bool flag, typename = typename std::enable_if<flag>::type> 
    void foo() { cout << "Yay" << endl; } // (A) 

    template <bool flag, typename = typename std::enable_if<!flag>::type> 
    void foo() { cout << "Nay" << endl; } // (B) 

otrzymuję ten błąd (pierwsza linia wskazuje definicji (B), drugi wskazując (A)):

error: 'template<bool flag, class> void Testable::foo()' cannot be overloaded 
error: with 'template<bool flag, class>> void Testable::foo()' 

Odpowiedz

5

kompilator narzeka ponieważ dwa szablony funkcji mają ten sam podpis. Pkt 1.3.18 w C++ 11 standard określa co podpis szablonu funkcja jest zdefiniowana przez:

<function template> nazwy, listy Typ parametru (8.3.5), wraz przestrzeni nazw (jeśli w ogóle), typ zwracany i lista parametrów szablonu

Jak widać, domyślne argumenty szablonu nie są częścią podpisu.

Można by obejść ten problem zmieniając definicję Testable następująco:

class Testable { 
public: 
    template <bool flag, typename std::enable_if<flag>::type* = nullptr> 
    void foo() { cout << "Yay" << endl; } // (A) 

    template <bool flag, typename std::enable_if<!flag>::type* = nullptr> 
    void foo() { cout << "Nay" << endl; } // (B) 
}; 
+0

To właściwie nadal mnie nie kompiluje (na gcc4.6.3). Otrzymuję 'no matching function dla wywołania 'Testable :: foo()'', gdy próbuję po prostu wywołać foo (). – Barry

+0

@Barry Musisz użyć argumentu szablonu 'foo'. Nie ma niczego, co mogłoby to wydedukować. Czy wypróbowałeś 'obj.foo ();'? – WhozCraig

+0

@WhozCraig - Tak, cała moja główna jest po prostu 'Testowalna t; t.foo (); ' – Barry

0

Jak wspomniano, dwie funkcje nie mogą mieć ten sam podpis.

Jednak mam inną poprawkę.

template<std::size_t> 
struct secret_enum { enum class type {}; }; 
template<bool b, std::size_t n=0> 
using EnableIf = typename std::enable_if< b, typename secret_enum<n>::type >::type; 

class Testable { 
public: 
    template <bool flag, EnableIf<flag, 0>...> 
    void foo() { cout << "Yay" << endl; } // (A) 

    template <bool flag, EnableIf<!flag, 1>...> 
    void foo() { cout << "Nay" << endl; } // (B) 
}; 

gdzie można wyliczyć swoje przeciążeń z 0, 1, itp, które generuje możliwie typ, który następnie ... do powiedzenia „0 lub więcej z nich”, a typy generowane są w zasadzie niemożliwe do generowania enum instancji .

Niestety, to nie działa w brzęczeniu 3.2. Działa w gcc 4.8.

Powiązane problemy