使用std :: enable_if

时间:2014-07-08 16:37:08

标签: c++ templates c++11 enable-if

我正在尝试使用std :: enable_if为一系列类型专门化一个函数。
这是我想要完成的更简单的版本。

#include <type_traits>
#include <string>

struct Ip
{};

template <typename T>
bool Equal(const std::string& s, const T& data)
{return s == data;}

template <typename T>
bool Equal(const std::string& s, const typename std::enable_if<std::is_integral<T>::value, T>::type& data)
{
    //int specific
}

template <typename T>
bool Equal(const std::string& s, const typename std::enable_if<std::is_floating_point<T>::value, T>::type& data)
{
    //Float specific
}

//Specialization
template <> bool Equal(const std::string& s, const Ip& data)
{
   //Ip specific
} 

int main()
{
    //Equal("21",21); // Do not compile
    Equal("21","42.5"); // Compile
}

但是在尝试编译时,带有std :: enable_if的模板函数似乎没有参与解析,因此编译器告诉我没有与我的函数调用匹配的函数。我尝试使用返回类型的std::enable_if,但也没有运气。我确信在这段代码中我有一些错误,或者我正在尝试以错误的方式执行此操作。
我试图不写每个int专门化(int,short,long ,很长,...),所以有人有这个解决方案吗?

2 个答案:

答案 0 :(得分:4)

我对代码进行了一些更改,从无约束功能模板开始。由于您分别处理算术类型,因此只有在T既不是整数也不是浮点时才应选择算法类型。

template <typename T>
typename std::enable_if<!std::is_integral<T>::value &&
                        !std::is_floating_point<T>::value, bool>::type 
    Equal(const std::string& s, const T& data)
{return s == data;}

现在,您为整数和浮点类型定义Equal的方式会导致T成为非推导的上下文。因此,将enable_if移动到虚拟模板参数以允许扣除(您也可以使用返回类型,如上所述)。

template <typename T,
          typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
bool Equal(const std::string& s, const T& data)
{
    //int specific
    return false;
}

template <typename T,
          typename std::enable_if<std::is_floating_point<T>::value, T>::type* = nullptr>
bool Equal(const std::string& s, const T& data)
{
    //Float specific
    return false;
}

最后,没有必要专门处理Ip,而是创建一个重载。

//Overload
bool Equal(const std::string& s, const Ip& data)
{
   //Ip specific
    return false;
}

Live demo

答案 1 :(得分:3)

以下作品:(https://ideone.com/G1vJKm

#include <string>
#include <type_traits>

struct Ip
{
    std::string ip;
};

template <typename T>
typename std::enable_if<!std::is_integral<T>::value && !std::is_floating_point<T>::value, bool>::type
Equal(const std::string& s, const T& data)
{return s == data;}

template <typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
Equal(const std::string& s, const T& data)
{
    //int specific
    return false;
}

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, bool>::type
Equal(const std::string& s, const T& data)
{
    //Float specific
    return false;
}

bool Equal(const std::string& s, const Ip& data)
{
   //Ip specific
    return false;
}

在你的情况下,

template <typename T>
bool Equal(const std::string& s, const T& data)

是所有T的有效候选者,也适用于积分和浮点。

您的其他模板函数,编译器无法推断T的{​​{1}}类型。

对于typename std::enable_if<std::is_integral<T>::value, T>::type版本,更简单的过载就足够了(并且首选)。