Search code examples
c++templatesenable-if

Using std::enable if for template with 3 generic arguments


I've already found a few threads to the topic of std::enable_if, but unfortunately I am not able to apply the examples to my code.

template<class From, class To, class Value>
struct convert
{
  static Value apply(Value value)
  {
    return value;
  }
};

I want this to be active only when From and To are the same, so I tried to use

std::enable_if<std::is_same<From,To>::value>::Value

But that doesn't work. How would I do this?

I also have these two specializations, to give you a better picture of my problem:

template<class From, class Value>
struct convert<From, kilometer, Value>
{
  static Value apply(Value value)
  {
    doSomething;
  }
};

template<class To, class Value>
struct convertImpl <kilometer, To, Value>
{
  static Value apply(Value value)
  {
    doSomethingElse;
  }
};

This is where my abguity problems come from. Right now I'm static_asserting the case that From and To are the same thus making the code to compile. But I would like to just return the value when those two are of the same type.


Solution

  • template<class From, class To, class Value>
    struct convert
    {
        template <typename F = From, typename T = To>
        static auto apply(Value value) -> typename std::enable_if<std::is_same<F,T>::value, Value>::type
        {
            static_assert(std::is_same<F, From>::value && std::is_same<T, To>::value, "");
            // no conversion
            return value;
        }
    
        template <typename F = From, typename T = To>
        static auto apply(Value value) -> typename std::enable_if<!std::is_same<F,T>::value, Value>::type
        {
            static_assert(std::is_same<F, From>::value && std::is_same<T, To>::value, "");
            // do conversion
            return value;
        }
    };
    

    DEMO

    Alternatively this can be implemented using a tag-based dispatching:

    template<class From, class To, class Value>
    struct convert
    {
        static Value apply(Value value)
        {
            using tag = std::integral_constant<bool, std::is_same<From, To>::value>; 
            return _apply(value, tag{});
        }
    
    private:
        static Value _apply(Value value, std::true_type)
        {
            // no conversion
            return value;
        }
    
        static Value _apply(Value value, std::false_type)
        {
            // do conversion
            return value;
        }
    };
    

    DEMO 2