【发布时间】: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++17。 Here 是带有代码的 Godbolt 链接。
【问题讨论】:
-
不得不抱怨,编译器没有其他构造函数可以使用。当
Traits::is_const为假时,您需要提供额外的构造函数。 -
thing()、thing(ptr_type)和thing(const thing&)怎么样?当Traits::is_const是false时,我不希望第四个构造函数存在。 -
@Corristo 错误消息来自
thing<traits<int*>> t;。应该选择thing(ptr_type)。 -
因为
Ptr不是constthing(const thing&)和thing(const thing<non_const_traits_type>&)具有相同的签名。