基于C++17的SFINAE:可靠检查复制赋值表达式有效性
C++17下可靠检查赋值表达式有效性的问题
请考虑以下类实现,重点关注Concrete<T>::copy_assign:
struct TypeErased { TypeErased() = default; TypeErased& operator=(TypeErased const& other) { copy_assign(other); return *this; } virtual void copy_assign(TypeErased const& other) = 0; virtual ~TypeErased(){} }; template <typename T> class Concrete : public TypeErased { public: template <typename... Args> Concrete(Args&&... args) : value(std::forward<Args>(args)...) {} T const& get_value() const { return value; } void copy_assign(TypeErased const& other) override final { copy_assign_impl(other); } private: template <typename U=T> void copy_assign_impl(TypeErased const& other) { if constexpr (std::is_copy_assignable_v<U>) { value = static_cast<Concrete<U> const&>(other).get_value(); } else { throw std::logic_error("Nope!"); } } T value; };
我的需求是:即使T不可复制赋值,也能通过constexpr-if实例化Concrete<T>对象;当尝试对T不可复制赋值的Concrete<T>执行复制赋值操作时,抛出运行时错误。
struct NoCopy { NoCopy() = default; NoCopy(NoCopy const&) = delete; NoCopy& operator=(NoCopy const&) = delete; }; int main() { // 以下实例化均可正常运行: Concrete<double> x1; // 平凡类型 Concrete<std::vector<double>> x2; Concrete<NoCopy> x3; Concrete<std::unique_ptr<double>> x4; Concrete<std::optional<NoCopy>> x5; }
当前问题在于,constexpr-if的判断条件并不全面:存在std::is_copy_assignable_v<T>为true,但value = static_cast<Concrete<T> const&>(other).get_value();表达式无效的场景,例如以下实例化均会触发编译错误:
Concrete<boost::optional<NoCopy>> x6; Concrete<std::vector<NoCopy>> x7; Concrete<std::vector<std::unique_ptr<double>>> x8; Concrete<boost::variant<std::string&, boost::optional<std::string>&>>; // 该类型来自外部库,无法修改
仅使用C++17特性,是否存在类型特性或SFINAE技巧,可可靠检查value = static_cast<Concrete<T> const&>(other).get_value();表达式的有效性?
注:此前针对boost::optional的相关问题已有提问。
内容的提问来源于stack exchange,提问作者joergbrech
相关产品推荐
相关产品推荐

