仅当某个模板具有给定类的特化时,如何std :: enable_if

Bul*_*net 2 c++ templates enable-if c++11

我有以下模板:

namespace std {
template<typename Enum>
typename std::enable_if<std::is_enum<Enum>::value, std::ostream&>::type
operator<<(std::ostream& strm, Enum e)
{
    return strm << helper_of<Enum>::to_string(e);
}
}
Run Code Online (Sandbox Code Playgroud)

这有助于谷歌测试在比较霍比特人时显示人类可读的诊断:

template <typename T> struct enumclass {}; // generic template

template <typename T>
using helper_of = typename enumclass<T>::helper; // more mnemonic

namespace MiddleEarth {
enum class Hobbit { Bilbo, Frodo, Sam };

struct HobbitHelper{
    std::string to_string(Hobbit H);
    Hobbit from_string(std::string const& s); // Hobbit-forming
};

template <> struct enumclass<Hobbit> {
    using helper = HobbitHelper; // links Hobbit to its helper
}
}
Run Code Online (Sandbox Code Playgroud)

enable_if是为了防止这个模板operator<<被应用于任何旧类(没有enable_if的天真版本对于已经具有流操作符的类是不明确的,例如std::string).

但是,如果有一个不专门的枚举enumclass,

enum class Wizard { Gandalf, Radagast, Saruman };
const Wizard g = Wizard::Gandalf, s = Wizard::Saruman;
Run Code Online (Sandbox Code Playgroud)

然后以下无法编译

EXPECT_EQ(g, s);
Run Code Online (Sandbox Code Playgroud)

error: no type named 'helper' in 'aws::enumclass<Wizard>'因为编译器将尝试应用模板operator<<,以向导.

是否有可能构造一个enable_if只应用此运算符<<如果有专门化enumclass<Enum>?谷歌测试然后将回退显示向导的原始字节,它将编译.

如果失败了,是否有可能构建一个enable_if只允许某个命名空间中的类型(例如MiddleEarth)?如果Wizard不在MiddleEarth命名空间中,这将解决问题.MiddleEarth中的所有枚举都应该具有专业性enumclass.

Bar*_*rry 5

您可以将helper_of替换移动到模板规范本身:

template <typename Enum,
          typename Helper = helper_of<Enum>>
std::ostream& operator<<(std::ostream& strm, Enum e)
{
    return strm << Helper::to_string(e);
}
Run Code Online (Sandbox Code Playgroud)

这样,如果helper_of替换失败(也就是说,enumclass不是专门用于给定的Enum),整个重载将由于SFINAE而被抛出而不是一个硬编译错误 - 因为现在我们处于替换的直接上下文中本身.