使用SFINAE根据是否存在特定的函数重载来选择函数 [英] Using SFINAE to select function based on whether a particular overload of a function exists

查看:85
本文介绍了使用SFINAE根据是否存在特定的函数重载来选择函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试根据是否存在重载 operator<(std :: ostream& ;, const T&)在两个模板化函数之间进行选择。 p>

示例:

  template< typename T,typename std :: enable_if< ; / *? * /,int> :: type = 0> 
std :: string stringify(const T& t)
{
std :: stringstream ss;
ss<< t;
return ss.str();
}

模板< typename T,类型名std :: enable_if< / *吗? * /,int> :: type = 0>
std :: string stringify(const T& t)
{
return运算符不超载<<;
}

struct Foo {};

int main()
{
std :: cout<< stringify(11)<< std :: endl;
std :: cout<< stringify(Foo {})<< std :: endl;
}

这可能吗?如果是这样,您将如何解决此问题?

解决方案

不需要 enable_if ,如果存在 operator <<,则使用表达式SFINAE选择正确的重载。

 命名空间详细信息
{
template< typename T>
自动stringify(std :: stringstream& ss,T const& t,bool)
-> decltype(ss<< t,void(),std :: string {})
{
ss< t;
return ss.str();
}

template< typename T>
自动stringify(std :: stringstream& ;, T const& int)
-> std :: string
{
return运算符不超载<<;
}
}

模板< typename T>
std :: string stringify(const T& t)
{
std :: stringstream ss;
return detail :: stringify(ss,t,true);
}

实时演示



stringify 函数模板委托给 detail :: stringify 函数模板之一。然后,如果表达式 ss<< ;,则选择第一个。 t 格式正确。未命名的 bool 参数用于消除两个 detail :: stringify 实现之间的歧义。由于主要的 stringify 函数将 true 传递为 detail :: stringify ,如果出现 operator<< 重载,第一个匹配会更好。否则,将选择第二个。



此表达式 decltype(ss<< t,void(),std :: string {} )在第一个 stringify 模板的尾随返回类型中,可能需要更详细的说明。在这里,我们有一个包含由逗号分隔的3个子表达式的单个表达式。



第一个, ss<< t 是确定该功能模板是否通过模板参数替换并将被添加到重载解决方案集中的因素。如果表达式格式正确,即如果所讨论的类型重载 operator<< ,就会发生这种情况。



中间子表达式 void()除了确保某些用户定义的内容外不做任何其他事情 operator,未选中(因为您不能使 operator,重载 void 参数类型)。



第三个也是最右边的子表达式 std :: string {} 决定 detail :: stringify 函数的返回类型。


I have been trying to choose between two templated functions based on whether an overload operator<<(std::ostream&, const T&) exists.

Example:

template <typename T, typename std::enable_if</* ? */, int>::type = 0>
std::string stringify(const T& t)
{
    std::stringstream ss;
    ss << t;
    return ss.str();
}

template <typename T, typename std::enable_if</* ? */, int>::type = 0>
std::string stringify(const T& t)
{
    return "No overload of operator<<";
}

struct Foo { };

int main()
{
    std::cout << stringify(11) << std::endl;
    std::cout << stringify(Foo{}) << std::endl;
}

Is this possible? And if so, how would you solve this problem?

解决方案

There's no need for enable_if, use expression SFINAE to select the correct overload when the operator<< is present.

namespace detail
{
    template<typename T>
    auto stringify(std::stringstream& ss, T const& t, bool)
        -> decltype(ss << t, void(), std::string{})
    {
        ss << t;
        return ss.str();
    }

    template<typename T>
    auto stringify(std::stringstream&, T const&, int)
        -> std::string
    {
        return "No overload of operator<<";
    }
}

template <typename T>
std::string stringify(const T& t)
{
    std::stringstream ss;
    return detail::stringify(ss, t, true);
}

Live demo

The stringify function template simply delegates to one of the detail::stringify function templates. Then, the first one is selected if the expression ss << t is well-formed. The unnamed bool parameter is being used for disambiguation between the two detail::stringify implementations. Since the primary stringify function passes true as the argument to detail::stringify, the first one will be a better match when the operator<< overload is present. Otherwise the second one will be selected.

This expression decltype(ss << t, void(), std::string{}) in the trailing return type of the first stringify template probably merits a more detailed explanation. Here we have a single expression consisting of 3 sub-expressions separated by the comma operator.

The first one, ss << t is what determines whether that function template passes template parameter substitution and will be added to the overload resolution set. This will occur if the expression is well-formed, i.e. if the type in question overloads operator<<.

The middle sub-expression, void() doesn't do anything other than ensure that some user-defined operator, is not selected (because you cannot overload operator, with a void parameter type).

The third, and rightmost, sub-expression, std::string{} is what determines the return type of the detail::stringify function.

这篇关于使用SFINAE根据是否存在特定的函数重载来选择函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆