我使用的是 Visual Studio 17.7 预览版 3,包括 Boost 1.67.0b1。
我是使用 enable_if
的老手了,但今天我尝试使用新的做事方式 - 一个虚拟的额外模板参数。
Boost.Range 不提供“这是一个范围”检查,所以我使用 range_value<X>::value
因为如果指定类型不是范围,则依赖类型不存在。这正是 SFINAE 的意义所在!当我给它一个 double
时,模板无法解析声明。 ,因此它应该不会出现错误而退出过载集。
#include <boost/range/value_type.hpp>
class Fizzer_t {
public:
using itemdef_t = std::pair<int, std::string_view>;
private:
std::vector<itemdef_t> playdef;
public:
template<typename R,
typename = typename boost::range_value<R>::type> // only call if R is a "range"
Fizzer_t (const R & range_of_itemdefs);
Fizzer_t (double); // dummy
};
void play2 {
Fizzer_t player3{ 3.14 };
}
当我给它一个有效的参数时,它就会编译。
当我给它 double
,而不是匹配其他构造函数,它提示
'type': is not a member of 'boost::range_iterator'
这绝对不是 SFINAE。
我在这里缺少什么?
最佳答案
问题在于如何 boost::range_value
类已定义。
namespace boost
{
template< class T >
struct range_value : iterator_value< typename range_iterator<T>::type >
{ };
}
因此,当编译器深入到代码中的行时
typename = typename boost::range_value<R>::type
不是那样boost::range_value<R>
没有 type
成员(member)typedef
,但是boost::range_value<R>
不是有效类型,因为它不能继承自 iterator_value< typename range_iterator<T>::type >
,因为那个也失败了。
因此原始错误:
error: no type named 'type' in 'struct boost::range_iterator<double, void>'
一个快速解决方法就是直接写
typename = typename boost::range_value<R>
e.i.删除 ::type
在最后。或者,您可以直接检查 boost::range_iterator<R>
是否有一个type
成员(member),
typename = typename boost::range_iterator<R>::type
关于templates - SFINAE 上缺少一些内容(虚拟模板参数形式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49826802/