使用SFINAE检查类型的函数std :: to_string是否存在

bpe*_*kes 3 c++ templates sfinae

我想创建一个功能模板,该模板专门用于可能已std::to_string应用到它们的类型,另一个模板专门用于我已经为其定义a的类mylib::to_string,并让其可能不属于其他实现或专门化的任何类型。

例:

// I only want this to be found if std::to_string exists for ItemType
template<typename ItemType>
void func(ItemType &i)
{
     std::cout << std::to_string(i);
}

// I only want this to be found if mylib::to_string exists for ItemType
template<typename ItemType>
void func(ItemType &i)
{
     std::cout << mylib::to_string(i);
}

// And finally, I'd like to be able to fall through to anything that has a << defined for streams
template<>
void func<MyClass>(MyClass &i)
{
     std::cout << MySpecialConverterFunc(i);
}
Run Code Online (Sandbox Code Playgroud)

我的std::enable_if语法总是有问题。您如何将其添加到第一个模板?

Sto*_*ica 5

For SFINAE you need not to specialize, but to overload. Which is saner than dealing with specializations anyway (those have quirks). SFINAE is a mechanism to guide overload resolution, not for choosing explicit specializations of function templates.

As for the check itself, you don't need enable_if really. Just a little bit of expression SFINAE will do:

template<typename ItemType>
auto func(ItemType &i) -> decltype(std::to_string(i), void())
{
     std::cout << std::to_string(i);
}

void func(MyClass &i)
{
     std::cout << MySpecialConverterFunc(i);
}
Run Code Online (Sandbox Code Playgroud)

In the above code, decltype is applied to a comma expression. The left hand side is std::to_string(i), if it isn't well-formed, the whole expression isn't well formed, and we get a substitution error, making the compiler discard that overload (the "not an error" part). If it's well-formed, the right hand side is a void() literal, so decltype resolves to void as you intended.

When substitution fails, all we are left with is the second overload, so it's picked. It would have been picked for this case anyway, because non-template overloads are always favored in overload resolution if the signature is the same. But adding a check to better guide the compiler in other cases is not a bad idea in and of itself.