Search code examples
c++c++11templatestemplate-meta-programming

Is it possible to define a group of template parameters and specialize it conditionally


struct TypeA {
    using data_t = int;
    enum { thread_create = pthread_create }; // ???
};

struct TypeB {
    using data_t = double;
    enum { thread_create = another_kind_of_thread_create }; // ???
};

template<typename T>
class Test {
public:
    void func() {
        T::thread_create(); // ???
    }
private:
    T::data_t a;
};

Test<TypeA> t1;
Test<TypeB> t2;

What I'm trying to do is to specialize the template class Test with one single template parameter.

As you see, data_t shouldn't be any problem but it doesn't seem that passing a function is easy. This piece of code will generate an error: error: enumerator value for 'thread_create' must have integral or unscoped enumeration type.

Is it possible to pass a function like this?


Solution

  • I if understand you correctly, you want to switch thread creation function and data type depending on the specialization. If so, why not sth like this?

    #include <type_traits>
    
    void pthread_create(void*, void*);
    void another_kind_of_thread_create(void*, void*);
    //my fakes. use your includes here
    
    struct TypeA {
        using data_t = int;
        using thread_create_t = void (*)(void*, void*);
        static constexpr thread_create_t  thread_create{pthread_create};
    };
    
    struct TypeB {
        using data_t = double;
        using thread_create_t = void (*)(void*, void*);
        static constexpr thread_create_t thread_create{another_kind_of_thread_create};
    };
    
    template<typename T>
    class Test : public T {
    public:
        void func() {
            T::thread_create(this, &a); //whatever, put here just to match the prototype...
        }
    private:
        typename T::data_t a;
    };
    
    Test<TypeA> t1;
    Test<TypeB> t2;
    
    static_assert(std::is_same<decltype(t1)::data_t, int>::value, "t1 should be int");
    static_assert(std::is_same<decltype(t2)::data_t, double>::value, "t2 should be double");
    
    

    demo