具有模板化类成员函数的 SFINAE
Posted
技术标签:
【中文标题】具有模板化类成员函数的 SFINAE【英文标题】:SFINAE with Templated class Member functions 【发布时间】:2018-12-11 04:57:21 【问题描述】:我正在尝试了解 SFINAE,但在尝试将其应用于模板类成员函数时遇到了问题。感谢Why doesn't SFINAE (enable_if) work for member functions of a class template?,我能够设置一个基本示例(Run online):
template<typename T>
class Foo
public:
template <typename U = T, typename std::enable_if_t<!std::is_same<U, int>::value && !std::is_same<U, float>::value,int> = 0>
void sfinae() // Foo<anything else>
std::cout << "sfinae default" << std::endl;
template <typename U = T, typename std::enable_if_t<std::is_same<U, int>::value,int> = 0>
void sfinae() // Foo<int>
std::cout << "sfinae int" << std::endl;
template <typename U = T, typename std::enable_if_t<std::is_same<U, float>::value,int> = 0>
void sfinae() // Foo<float>
std::cout << "sfinae float" << std::endl;
;
对此我有两个后续问题: 1. 如何分离成员函数的声明和定义? 我尝试了类似下面的定义:
template <typename T>
template <typename U = T, typename std::enable_if_t<!std::is_same<U, int>::value && !std::is_same<U, float>::value,int> = 0>
void Foo<T>::sfinae() // Foo<anything else>
std::cout << "sfinae default" << std::endl;
但这会导致编译错误。
2. 包罗万象的默认情况(打印 sfinae-default)目前必须写为not(type1, type2,...)
,这可能是巨大的。是否有更短/更清洁的解决方案?
编辑: 根据@Jans 的回答,这里是corrected solution。
【问题讨论】:
【参考方案1】:在 out of line 定义中,您删除了默认参数,它们取自声明:
template <class T>
template <typename U, typename std::enable_if_t<!std::is_same<U, int>::value && !std::is_same<U, float>::value,int>>
void Foo<T>::sfinae() // Foo<anything else>
std::cout << "sfinae default" << std::endl;
其他人也一样
包罗万象的默认情况(打印 sfinae-default)目前必须写为
not(type1, type2,...)
,这可能是巨大的。是否有更短/更清洁的解决方案?
为此,您需要添加一个额外的参数来对重载进行排名,将最低排名赋予包罗万象的重载,这通常使用省略号参数并不比任何其他参数类型更好的事实来完成:
template <typename U = T>
void sfinae(...);
template <typename U = T, typename std::enable_if_t<std::is_same<U, int>::value,int> = 0>
void sfinae(int);
template <typename U = T, typename std::enable_if_t<std::is_same<U, float>::value,int> = 0>
void sfinae(int);
Foo<char>.sfinae(0); // select the catch-all
这意味着由于...
比任何其他参数都差(int
优于...
),因此只有在其他两个无法调用时才考虑重载sfinae(...)
,即如果他们是 SFINAE。
【讨论】:
谢谢,我可以确认这是有效的!也就是说:(1)没有额外的“int”参数是不可能的吗? (2) 你能否在你的答案中添加一些关于排名如何运作的细节?以上是关于具有模板化类成员函数的 SFINAE的主要内容,如果未能解决你的问题,请参考以下文章