Search code examples
c++templatestemplate-meta-programmingsfinae

How can you check whether a templated class has a member function?


Is it possible to write a template that changes behavior depending on if a certain member function is defined on a class?

Here's a simple example of what I would want to write:

template<class T>
std::string optionalToString(T* obj)
{
    if (FUNCTION_EXISTS(T->toString))
        return obj->toString();
    else
        return "toString not defined";
}

So, if class T has toString() defined, then it uses it; otherwise, it doesn't. The magical part that I don't know how to do is the "FUNCTION_EXISTS" part.


Solution

  • Yes, with SFINAE you can check if a given class does provide a certain method. Here's the working code:

    #include <iostream>
    
    struct Hello
    {
        int helloworld() { return 0; }
    };
    
    struct Generic {};    
    
    // SFINAE test
    template <typename T>
    class has_helloworld
    {
        typedef char one;
        struct two { char x[2]; };
    
        template <typename C> static one test( decltype(&C::helloworld) ) ;
        template <typename C> static two test(...);    
    
    public:
        enum { value = sizeof(test<T>(0)) == sizeof(char) };
    };
        
    int main(int argc, char *argv[])
    {
        std::cout << has_helloworld<Hello>::value << std::endl;
        std::cout << has_helloworld<Generic>::value << std::endl;
        return 0;
    }
    

    I've just tested it with Linux and gcc 4.1/4.3. I don't know if it's portable to other platforms running different compilers.