使用`std :: enable_if`

时间:2019-01-01 15:07:06

标签: c++ sfinae enable-if

我有一个使用特定指针类型参数化的模板类型。 (如迭代器)。我希望此类型可以使用const限定符(例如thing<const int*>(const thing<int*>&)隐式转换为自身的版本。我希望在指针已经为const时禁用此构造函数,因为它与默认的复制构造函数冲突。目前,我有一些类似于以下代码片段的内容:

#include <type_traits>

template <typename Ptr>
struct traits {
    using ptr_type = Ptr;
    static constexpr bool is_const = std::is_const_v<std::remove_pointer_t<ptr_type>>;
    template <typename _Ptr> using rebind = traits<_Ptr>;
};

template <typename Traits>
struct thing {
    using ptr_type = typename Traits::ptr_type;
    using non_const_ptr_type = std::add_pointer_t<std::remove_const_t<std::remove_pointer_t<ptr_type>>>;
    using non_const_traits_type = typename Traits::template rebind<non_const_ptr_type>;

    thing(ptr_type p = nullptr) : ptr_(p) {}
    thing(const thing&) = default;

    template <typename = std::enable_if_t<Traits::is_const>>
    thing(const thing<non_const_traits_type>& other) :
        ptr_(const_cast<ptr_type>(other.ptr_)) {}

    ptr_type ptr_;

    template <typename> friend struct thing;
};

int main() {
    thing<traits<      int*>> t;
    thing<traits<const int*>> j(t);
}

thing类型从traits类型获取其参数,因为它可以更准确地表示我的真实代码。我试图使用std::enable_if禁用构造函数,但由于某些原因,编译器一直抱怨enable_if上的non-const thing

error: no type named 'type' in 'struct std::enable_if<false, void>'
    using enable_if_t = typename enable_if<_Cond, _Tp>::type;

enable_if放入构造函数的参数列表中也无济于事。使用-std=c++17与GCC 8一起编译。 Here是带有代码的Godbolt链接。

1 个答案:

答案 0 :(得分:3)

您需要使std::enable_if依赖于构造函数的模板参数而非类:

template <class T = Traits, typename = std::enable_if_t<T::is_const>>
thing(const thing<non_const_traits_type>& other) :
    ptr_(const_cast<ptr_type>(other.ptr_)) {}