2016-05-23 8 views
0

ich diesen Code ausführen kann, aber wenn ich die 3-kommentierten Zeilen ermöglichen es nicht mehr nicht kompiliert und gibt den folgenden Fehler:Template Spezialisierung basiert auf Argumente von Template-Parameter Elementfunktion

1>d:\git\testprojekt\testprojekt\testprojekt.cpp(41): warning C4346: 'first_argument<F>::type': dependent name is not a type 
1> d:\git\testprojekt\testprojekt\testprojekt.cpp(41): note: prefix with 'typename' to indicate a type 
1> d:\git\testprojekt\testprojekt\testprojekt.cpp(43): note: see reference to class template instantiation 'Bla<Type>' being compiled 
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(41): error C2923: 'DoStuff': 'first_argument<F>::type' is not a valid template type argument for parameter 'Arg' 
1> d:\git\testprojekt\testprojekt\testprojekt.cpp(22): note: see declaration of 'first_argument<F>::type' 

Meine Idee, warum Es funktioniert nicht, dass der Compiler sicherstellen will, dass Bla für alle Arten von Template-Parametern kompiliert, aber first_argument kann nur Template-Parameter verarbeiten, für die operator() definiert ist. Weiß jemand, wie man dieses Beispiel funktioniert? Ich brauche es, um eine Klasse zu wählen, hier doStuff, basierend darauf, ob der Template-Parameter operator() ein Argument akzeptiert oder nicht, in einer anderen Template-Klasse, hier Bla.

#include <iostream> 


template<typename F, typename Ret> 
void helper(Ret(F::*)()); 

template<typename F, typename Ret> 
void helper(Ret(F::*)() const); 


template<typename F, typename Ret, typename A, typename... Rest> 
char helper(Ret(F::*)(A, Rest...)); 

template<typename F, typename Ret, typename A, typename... Rest> 
char helper(Ret(F::*)(A, Rest...) const); 

template<typename F> 
struct first_argument { 
    typedef decltype(helper(&F::operator())) type; 
}; 

template <typename Functor, typename Arg = first_argument<Functor>::type> 
struct DoStuff; 

template <typename Functor> 
struct DoStuff<Functor, char> 
{ 
    void print() { std::cout << "has arg" << std::endl; }; 
}; 

template <typename Functor> 
struct DoStuff<Functor, void> 
{ 
    void print() { std::cout << "does not have arg" << std::endl; }; 
}; 


template <typename Type> 
struct Bla 
{ 
    //DoStuff<typename Type> doStuff; 
    //void print() { doStuff.print(); }; 
}; 



int main() 
{ 
    struct functorNoArg { 
     void operator()() {}; 
    }; 

    struct functorArg { 
     void operator()(int a) { std::cout << a; }; 
    }; 

    auto lambdaNoArg = []() {}; 
    auto lambdaArg = [](int a) {}; 


    std::cout << std::is_same<first_argument<functorArg>::type,int>::value <<std::endl; // this works 

    DoStuff<functorArg> doStuff; 
    doStuff.print(); 

    DoStuff<functorNoArg> doStuff2; 
    doStuff2.print(); 

    DoStuff<decltype(lambdaArg)> doStuff3; 
    doStuff3.print(); 

    DoStuff<decltype(lambdaNoArg)> doStuff4; 
    doStuff4.print(); 

    Bla<functorArg> bla; 
    //bla.print(); 

    return 0; 
} 

Dank aller Schablonen nerds für die Hilfe :)

+1

Sie nicht 'typename' wo Sie sohuld, und Sie setzen' typename' wo sollten Sie nicht –

+1

, wenn der Compiler sagte, dass Sie 'type' fehlen, es bedeutet nicht, DoStuff doStuff ; ', es bedeutete' typename Arg = typenname first_argument :: type ' –

Antwort

1

In Ihrem struct Bla sollten Sie sagen DoStuff<Type> doStuff; (Typname nicht erforderlich ist oder hier erlaubt).

In (korrigierte Version):

template <typename Functor, typename Arg = typename first_argument<Functor>::type> struct DoStuff;

Sie wurden typename vor first_argument<Functor>::type fehlt.

+0

Ah danke, ja der eine typename war nur ein paar dumme Sachen, die ich versuchte zu machen, nachdem es anfänglich nicht funktionierte: P – bodzcount

Verwandte Themen