【问题标题】:Disabling a constructor entirely using `std::enable_if`使用 `std::enable_if` 完全禁用构造函数
【发布时间】:2019-01-01 15:07:06
【问题描述】:

我有一个模板类型,它是用某种指针类型参数化的。 (就像一个迭代器)。我希望这种类型可以隐式地转换为具有 const 限定符的自身版本(例如thing<const int*>(const thing<int*>&)。我希望在指针已经为 const 时禁用此构造函数,因为它与默认的复制构造函数发生冲突。目前我有类似于这个sn-p的代码:

#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 类型从特征类型获取其参数,因为这更准确地代表了我的真实代码。我尝试使用std::enable_if 禁用构造函数,但由于某种原因,编译器一直在抱怨non-const thing 上的enable_if

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

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

【问题讨论】:

  • 不得不抱怨,编译器没有其他构造函数可以使用。当Traits::is_const 为假时,您需要提供额外的构造函数。
  • thing()thing(ptr_type)thing(const thing&amp;) 怎么样?当Traits::is_constfalse 时,我不希望第四个构造函数存在。
  • @Corristo 错误消息来自thing&lt;traits&lt;int*&gt;&gt; t;。应该选择thing(ptr_type)
  • 因为 Ptr 不是 const thing(const thing&amp;)thing(const thing&lt;non_const_traits_type&gt;&amp;) 具有相同的签名。

标签: c++ sfinae enable-if


【解决方案1】:

您需要使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_)) {}

【讨论】:

    猜你喜欢
    • 2022-11-20
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 2013-07-24
    • 1970-01-01
    • 2019-10-11
    相关资源
    最近更新 更多