c++templatesreadable

How to explicitly let user know the requirement of template parameter?


For example, I have a class

// Require T has method T::A(arguments), T::B(arguments), since they will
// be used in the class template.
template<class T>
class Foo
{
    void Fun()
    {
        mT.A();
        mT.B();
    }
};

Want to generate more readable code. Any good design to explicitly let user know the requirement of template parameter?


Solution

  • In C++11 you can combine this answer with static_assert to provide more useful compiler error messages. For example:

    #define HAS_MEM_FUNC(func, name)                                    \
        template <typename T>                                           \
        class name {                                                    \
            typedef char one;                                           \
            typedef long two;                                           \
            template <typename C> static one test( decltype(&C::func)); \
            template <typename C> static two test(...);                 \
        public:                                                         \
            enum { value = sizeof(test<T>(0)) == sizeof(char) };        \
        }
    
    HAS_MEM_FUNC(A, has_A);
    HAS_MEM_FUNC(B, has_B);
    
    template<class T>
    class Foo
    {
    public:
        void Fun()
        {
            static_assert(has_A<T>::value,
                          "Template parameter does not contain member function `A`."); 
            static_assert(has_B<T>::value,
                            "Template parameter does not contain member function `B`."); 
    
            mT.A();
            mT.B();
        }
        T mT;
    };
    

    Now the code

    Foo<int> blah;
    blah.Fun();
    

    gives the error messages:

    test.cpp:21:9: error: static assertion failed: Template parameter does not contain member function A.
    test.cpp:23:9: error: static assertion failed: Template parameter does not contain member function B.
    test.cpp:26:9: error: request for member ‘A’ in ‘((Foo<int>*)this)->Foo<int>::mT’, which is of non-class type ‘int’
    test.cpp:27:9: error: request for member ‘B’ in ‘((Foo<int>*)this)->Foo<int>::mT’, which is of non-class type ‘int’