c++c++11templatessfinae

C++ function dispatch based on user defined input type category (C++11/14 friendly)


I want to dispatch functions based on user defined "tag" of my input types. For example, I defined a tag called SomeSpecificObjectType and in class Object I mark this class as a SomeSpecificObjectType.

struct SomeSpecificObjectType{};

template<typename T>
class Object
{
    public:
    Object(T&&in): m_data(in){};
    typedef SomeSpecificObjectType ObjectTag;  
    T m_data;
};

Now I have another object, which doesnt share this tag. So I dont touch it.

template<typename T>
class OtherObject
{
    public:
    OtherObject(T&&in): m_data(in){};
    T m_data;
};

Now I define a struct to check for the tag I defined above.

template<typename T, typename Enable=void>
struct is_some_specific_object_type
{
    static constexpr bool value = false;
};

template<typename T>
struct is_some_specific_object_type<T, typename std::enable_if<std::is_same<typename T::ObjectTag, SomeSpecificObjectType>::value>::type>
{
    static constexpr bool value = true;
};

My functions:

template<typename T, typename std::enable_if<!is_some_specific_object_type<T>::value>::type* = nullptr>
void some_func(const T & data)
{
    std::cout <<"something" <<std::endl;
}

template<typename T, typename std::enable_if<is_some_specific_object_type<T>::value>::type* = nullptr>
void some_func(const T & data)
{
    std::cout <<"something else" << std::endl;
}

This seems work.

However, imagine I have class where its definition is hidden from me (HiddenObject) - this means I am unable to just add the "tag" SomeSpecificObjectType to this class. Essentially I want is_some_specific_object_type::value == true for this HiddenObject. Is there a way to do it without edditing the class HiddenObject

template<typename T>
class HiddenObject
{
    public:
    HiddenObject(T&&in): m_data(in){};
    T m_data;
};

Final desired result:

int main()
{
    Object obj(123);
    OtherObject o_obj(123);

    some_func(obj);
    some_func(o_obj);

    //HiddenObject h_obj(123);
    //some_func(h_obj); ---> print "something else"

    return 0;
}

Eddit: Someone didnt like I used the word "trait", I will repalce this word with Tag, seems more fitting to avoid confusion.


Solution

  • Just add specialization of is_some_specific_object_type for HiddenObject:

    template <typename T> struct is_HiddenObject : std::false_type {};
    template <typename T> struct is_HiddenObject<HiddenObject<T>> : std::true_type {};
    
    template<typename T>
    struct is_some_specific_object_type<T, std::enable_if_t<is_HiddenObject<T>::value>> : std::true_type{};
    

    Demo

    Notice that you might have to add/rearrange the specializations if your type (HiddenObject) matches several specializations.