I've been trying to create specializations of templated class methods such that I would have different method definitions which the compiler selects from based on whether an argument is an integral type of an enum class, but clang gives me this error:
Out-of-line definition of 'ParseString' does not match any declaration in 'MyData'
While GCC gives the following:
error: prototype for 'typename std::enable_if::value, void>::type MyData::ParseString(T&, std::string)' does not match any in class 'MyData'
error: candidate is: template static void MyData::ParseString(T&, std::string)
The following code was used to produce these errors. I've experimented with other ways of using enable_if
, such as in a template parameter rather than the return type, but nothing so far has worked. If I make the templated functions non-class functions instead of class methods, then they work fine. (Removing the static makes no difference.)
Is there a way to use enable_if
for templated class methods, or a better way to achieve the same thing?
#include <string>
#include <type_traits>
#include <utility>
class MyData
{
public:
MyData() = default;
MyData(std::pair<std::string, std::string> string_representations);
std::pair<std::string, std::string> ToStrings();
enum class MyEnum
{
A = 0,
B = 1
};
int integral_value;
MyEnum enum_value;
private:
template<typename T>
static void ParseString(T&, std::string);
};
MyData::MyData(std::pair<std::string, std::string> string_representations)
{
ParseString(integral_value, string_representations.first);
ParseString(enum_value, string_representations.second);
}
std::pair<std::string, std::string> MyData::ToStrings()
{
return std::make_pair(std::to_string(integral_value), std::to_string((unsigned long)enum_value));
}
template<typename T>
typename std::enable_if<std::is_enum<T>::value, void>::type
MyData::ParseString(T& setting, std::string representation)
{
setting = (T)std::stoul(representation);
}
template<typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
MyData::ParseString(T& setting, std::string representation)
{
setting = std::stoi(representation);
}
(In this example there's only one integral and one enum member of the class, but if you're wondering why the templated function would be useful, imagine if the class had multiple different enum and integral type members.)