2016-04-29 16 views
15

Używając parametrów szablonu szablonu można przekazać do klasy klasę szablonową bez określania typów na swoich parametrach. Zastanawiam się, czy istnieje sposób, aby przejść do szablonu szablonu szablonu szablonowej sygnatury funkcji, aby móc wyspecyfikować, który wariant funkcji ma być uważany za przyszły.Czy istnieje sposób przekazywania szablonowego podpisu funkcji jako szablonu szablonu parametr

Żeby było jasne - wiem, że nie mogę tego zrobić:

template <class T> 
void foo() { /*...*/ } 

template <template <class...> class FooType> 
struct Foo { /*...*/ }; 

int main() { 
    Foo<decltype(foo)> f; 
} 

Ale jakoś Chciałbym, aby móc przejść na matrycy podpis funkcji do Foo. Czy to możliwe?

Odpowiedz

7

W poniższym przykładzie mamy parametr szablonu szablonu, który akceptuje preferowany podpis dla funkcji.
Ze względu na specjalizację i brak treści dla klasy szablonu akceptowane są tylko typy na podpalenie.
Jest to uogólnienie co PO rzeczywiście zapytał:

#include<cassert> 

template<typename F> 
struct S; 

template<typename R, typename... Args> 
struct S<R(Args...)> { 
    using type = R(*)(Args...); 
}; 

template<template<typename> class F> 
struct T { 
    typename F<void(int)>::type ft; 
    typename F<double(double, double)>::type gt; 
}; 

void f(int) { } 
double g(double x, double y) { return x+y; } 

int main() { 
    T<S> t; 
    t.ft = f; 
    t.gt = g; 
    t.ft(42); 
    auto v = t.gt(1., 1.); 
    assert(v == 2.); 
} 
+1

Tak, 'using' załatwia sprawę tutaj. To podejście wydaje się być nawet czystsze niż szablonowe "używanie" ... –

+0

Czy mogę zapytać, za co go używasz? Po prostu ciekawość ... Nie widzę żadnego zastosowania dla 'T', gdzie nie mogę użyć po prostu' S'. – skypjack

+0

Oczywiście powstało pytanie z innego archiwum: http://stackoverflow.com/questions/36655835/better-pattern-for-partial-specialization-disambiguation-precedence-chain/36657353#36657353 Chciałem zaproponować ogólny tag to byłby w stanie zaakceptować zarówno szablon szablonu, jak i funkcję z danym podpisem ... Wtedy zdałem sobie sprawę, że to nie jest trywialne zadanie ... :) –

3

szablon szablonu jest nadal szablonem.

template <class T> 
void foo() { /*...*/ } 

template <typename T> 
struct Foo { /*...*/ }; 

int main() { 
    Foo<decltype(foo<int>)> f; 
} 
+0

Jestem szczególnie zainteresowany w przekazywaniu szablonie podpisu funkcji ... –

3

Jak widać w this answer

szablon wskaźnika funkcji jest nielegalne w C++

mówi C++ standard w $ 14/1,

szablonu definiuje rodzinę klas lub funkcji.

Dalej cytuje połączonej odpowiedzi:

Należy pamiętać, że nie mówi „Szablon definiuje rodzinę klas, funkcje lub wskaźników funkcji

jednak możesz podać konkretne wskaźniki funkcji i specjalizować się na ich podpisie:

#include <iostream> 

template <class T> 
void foo(T) { } 

template <typename> 
struct Foo; 

template<typename T> 
struct Foo<void(T)> 
{ 
    void cb() { std::cout << "T\n"; } 
}; 

template<> 
struct Foo<void(int)> 
{ 
    void cb() { std::cout << "int\n"; } 
}; 

template<> 
struct Foo<void(double)> 
{ 
    void cb() { std::cout << "double\n"; } 
}; 

int main() 
{ 
    Foo<decltype(foo<int >)>().cb(); // outputs 'int' 
    Foo<decltype(foo<double>)>().cb(); // outputs 'double' 
    Foo<decltype(foo<char >)>().cb(); // outputs 'T' 
    return 0; 
} 
2

Nie można przekazać szablonu funkcji jako argumentu. Co ty może wystarczy owinąć szablon funkcji w lambda wygenerowania biorąc parametr tag:

template <class T> struct tag_t { using type = T; }; 

template <class T> 
void foo() { ... } 

template <class F> 
void call_func_with(F f) { 
    f(tag_t<int>{}); 
    f(tag_t<double>{}); 
} 

call_with_func([](auto tag) { foo<decltype(tag)::type>(); }); 

Tutaj f(tag_t<X>{}) dzwoniąc foo<X>(), zgodnie z zapotrzebowaniem.

8

Nie mogłem uwierzyć, że nie jest to możliwe, więc szukałem trochę i znalazłem sposób, aby zrobić dokładnie to, co chciałem. Użyłem matrycy using ze składnią:

template <template<class... Args> class FooType> 
struct Foo { 
    FooType<int> ft; 
}; 

template <class Res, class... Args> 
using FooSignature = Res(*)(Args...); 

int foo() { 
    return 1; 
} 

int main() { 
    Foo<FooSignature> f; 
    f.ft = foo; 
} 

To jednak wciąż pozostawia pytanie, jak to może być możliwe, ponieważ stan standardowy coś przeciwnego.

Powiązane problemy