1

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");
}
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • 1
    I don't really understand what you want, can you give an example of the desired functionality? Is [n3601](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3601.html) relevant? – Mankarse May 20 '13 at 14:09
  • @Mankarse: This is a library for some external interprocess communication mechanism which is not strongly typed. There are various explicit specializations of a class template, each of which contain the code necessary to convert from the interprocess communication version of the data (e.g. `VARIANT`) into C++ style types. Then there's a member function template calling the class template (in order to make partial specializations possible). – Billy ONeal May 20 '13 at 14:15
  • @BillyONeal: Can't you then introduce a partial specialization for that class that gets selected if the type is an enum? What's the definition of the primary class template? – Andy Prowl May 20 '13 at 14:20
  • @Andy: I don't know. I'm asking how one would do that. – Billy ONeal May 20 '13 at 14:23

2 Answers2

2

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);
}
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
1

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 :)

jrok
  • 54,456
  • 9
  • 109
  • 141
  • The main reason I used a class is that this conversion machinery is used in multiple places; and the SFINAE would need to be done in each place. – Billy ONeal May 20 '13 at 16:49