2016-02-09 21 views
7

Czy istnieje jakiś sposób, aby wywołać funktor operator()(int) o klasie szablonu Foo jak pokazano poniżej (online version)Wywołanie szablonie funktor w szablonie klasy

template<typename T> 
struct Foo 
{ 
    template<typename U> 
    void operator()(int) 
    { 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    Foo<char> foo; 
    foo<bool>(42); 
} 

Dostaję komunikat o błędzie w gcc 4.9. 3

error: expected primary-expression before ‘bool’ 
    foo<bool>(42); 

ja dołączana funktor z template jeżeli funkcja nie jest członkiem funktor i został prefiksem ::, . lub ->. Bez pomocy kompilator nie mógł wiedzieć, jak przetworzyć to wyrażenie; jako funktor lub instancję anonimowego obiektu typu foo<int>.

Odpowiedz

5

Będzie działać z;

foo.operator()<bool>(42); 

Operatorzy grać najlepiej z przewidywanych rodzajów szablon argumentu.

Nie podaje się wystarczająco szczegółowych informacji na temat kontekstu, w którym jest to używane, jako alternatywy, które można rozważyć;

  • dzięki czemu operator może wywołać funkcję użytkownika, a tym samym pozwalają na jednoznaczne argumenty typu szablon
  • mechanizm tag wysyłka
  • zaakceptować typ U jako argument

Na przykład;

template<typename U> 
void operator()(int, U&& /*initial*/) 
{ 
    // use the initial value of U 
} 
// called as... 

foo(42, true); // U is bool in your example 

Lub po prostu funkcja członka;

template<typename U> 
void my_func(int) 
{ 
} 
// called as... 

foo.my_fun<bool>(42); 
+0

"Operatory grają najlepiej z wydedukowanymi typami argumentów" - warto o tym pamiętać. Pominąłem jednak "&&". – Olumide

+0

@Oumide. Argument "U &&" jest używany tylko z myślą, że jeśli typ był bardziej złożony niż prymitywny, 'std :: move' może być użyty lub' U && 'może również powiązać tymczasowy. Proste 'U' również będzie działało dobrze. – Niall

5

Tak, ale ona jest brzydka:

foo.operator()<bool>(42); 
3

Niestety trzeba by użyć foo.operator()<bool>(42); do tego. foo<bool> jest ważny dla takich rzeczy jak szablony zmiennych C++ 14, a nie dla operatorów szablonów.

Co można zrobić, to tag typ i przekazać, że jako argument operatora połączeń wyprowadzić odpowiedni rodzaj:

//tag 
template <typename T> 
struct type{}; 

template<typename T> 
struct Foo 
{ 
    template<typename U> 
    //deduction on the tagged type 
    void operator()(type<U>, int) 
    { 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    Foo<char> foo; 
    foo(type<bool>{}, 42); 
    // ^^^^^^^^^^^^ pass tag 
} 

można zrobić to trochę ładniejszy przy użyciu C++ 14 zmiennych szablonów dla tagu:

template <typename T> 
struct type_t{}; 

//variable template for nicer usage 
template <typename T> 
type_t<T> type; 

template<typename T> 
struct Foo 
{ 
    template<typename U> 
    void operator()(type_t<U>, int) 
    { 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    Foo<char> foo; 
    foo(type<bool>, 42); 
    //don't need {}^ 
}