【问题标题】:Missing something on SFINAE (dummy template argument form)SFINAE 上缺少某些东西(虚拟模板参数形式)
【发布时间】:2018-04-14 00:42:16
【问题描述】:

我正在使用 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': 不是'boost::range_iterator'的成员

这绝对是不是 SFINAE。


我在这里错过了什么?

【问题讨论】:

标签: templates visual-c++ c++17 sfinae


【解决方案1】:

问题在于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&lt;R&gt; 没有type 成员typedef,而是boost::range_value&lt;R&gt; 不是有效类型,因为它不能从iterator_value&lt; typename range_iterator&lt;T&gt;::type &gt; 继承,因为那个也失败了.

因此原始错误:

error: no type named 'type' in 'struct boost::range_iterator<double, void>'

一个快速的解决方法是写

typename = typename boost::range_value<R>

e.i.最后删除::type。或者,您可以直接检查boost::range_iterator&lt;R&gt; 是否有type 成员,

typename = typename boost::range_iterator<R>::type

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多