Question

I have a function template powered by a set of class template explicit specializations giving syntax like

abc.GetAs<DesiredType>("Name");

(where GetAs<t> is something like:

template<typename T>
T GetAs(wchar_t const* propName) const
{
    typedef Converter<T> Converter;
    auto thing = Get(propName);
    return Converter::Convert(thing);
}

)

I would like to have a specialization for DesiredType when that type is an enumeration, so that the returned type matches the underlying type of the enumeration (or enum class).

Is that possible or do clients just have to specify the underlying type themselves?


I'm trying to allow code like this:

enum class Example
{
    One,
    Two
}

int main()
{
    foo_ipc_class ic(L"/// Construct me");
    // Today, calls the primary template rather than an explicit
    // specialization for an integral type.
    Example ex = ic.GetAs<Example>(L"Property Name");
}
Was it helpful?

Solution

As it's impossible to partially specialise function templates, you'll have to change your implementation to use the "delegate-to-class" trick:

#include <type_traits>

// Class to delegate to
template <typename T, bool isEnum = std::is_enum<T>::value>
struct GetAs_Class {
  typedef your_return_type ReturnType;
  static ReturnType GetAs(your_parameters) { your_code; }
};

// Partial specialisation    
template <typename T>
struct GetAs_Class<T, true> {
  typedef specialisation_return_type ReturnType;
  static ReturnType GetAs(your_parameters) { specialisation_code; }
};


// Your function now delegates to the class
template <typename T>
typename GetAs_Class<T>::ReturnType GetAs(your_parameters) {
  return GetAs_Class<T>::GetAs(your_arguments);
}

OTHER TIPS

You could use SFINAE to enable/disable overloads based on whether template parameter is an enum or not. std::is_enum and std::underlying_type come handy. I wrote GetAs as a free function for simplicity:

#include <type_traits>
#include <iostream>

template<typename T>
struct identity {
    typedef T type;
};

template<typename T>
typename std::enable_if<!std::is_enum<T>::value, identity<T>>::type::type
GetAs(wchar_t const*)
{
    std::cout << "general\n";
    // return something
}

template<typename T>
typename std::enable_if<std::is_enum<T>::value, std::underlying_type<T>>::type::type
GetAs(wchar_t const*)
{
    std::cout << "enum\n";
    // return something
}

enum class E : short {
};

int main()
{
    GetAs<int>(L"hm");
    GetAs<E>(L"hm");
}

It's pretty ugly, but so is delegating to a class to mimic partial specializations of function templates, IMO :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top