std::is_copy_assignable 和 boost::Optional 的意外行为

问题描述 投票:0回答:1

如果我删除类型的复制构造函数和/或复制赋值构造函数

Bar

struct Bar {
    Bar() = default;
    Bar(Bar const&) = delete;
};

std::optional<Bar>
不可复制分配。

using T = std::optional<Bar>;
static_assert(!std::is_copy_assignable_v<T>);

这正是我所期望的。对于

boost::optional<Bar>
来说似乎也是如此,但不幸的是
std::is_copy_assignable_v
的计算结果为 true。

using T = boost::optional<Bar>;
static_assert(std::is_copy_assignable_v<T>); // why doesn't this fail?

因此,以下代码无法编译:

template <typename T>
void foo() {
    if constexpr (std::is_copy_assignable_v<T>){
        T lhs;
        T rhs;
        lhs = rhs;
    } else {
        std::cout<< "Nope!\n";
    }
}

int main()
{
    foo<std::optional<Bar>>();  // works, prints "Nope!"
    foo<boost::optional<Bar>>(); // compiler error
}

GCC 13.2 的编译器错误:

In file included from /opt/compiler-explorer/libs/boost_1_84_0/boost/optional.hpp:15,
                 from <source>:4:
/opt/compiler-explorer/libs/boost_1_84_0/boost/optional/optional.hpp: In instantiation of 'void boost::optional_detail::optional_base<T>::construct(argument_type) [with T = Bar; argument_type = const Bar&]':
/opt/compiler-explorer/libs/boost_1_84_0/boost/optional/optional.hpp:277:20:   required from 'void boost::optional_detail::optional_base<T>::assign(const boost::optional_detail::optional_base<T>&) [with T = Bar]'
/opt/compiler-explorer/libs/boost_1_84_0/boost/optional/optional.hpp:249:19:   required from 'boost::optional_detail::optional_base<T>& boost::optional_detail::optional_base<T>::operator=(const boost::optional_detail::optional_base<T>&) [with T = Bar]'
/opt/compiler-explorer/libs/boost_1_84_0/boost/optional/optional.hpp:1099:15:   required from 'void foo() [with T = boost::optional<Bar>]'
<source>:34:34:   required from here
/opt/compiler-explorer/libs/boost_1_84_0/boost/optional/optional.hpp:410:8: error: use of deleted function 'Bar::Bar(const Bar&)'
  410 |        ::new (m_storage.address()) unqualified_value_type(val) ;
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:19:5: note: declared here
   19 |     Bar(Bar const&) = delete;
      |     ^~~
Compiler returned: 1

https://godbolt.org/z/dd3r63KG8

为什么代码不能与

boost::optional
一起使用?

我正在编写一个通用库,它依赖于带有

std::is_assignable_v<T>
的 constexpr-if 块。是否有一种我可以使用或自己编写的替代类型特征,可以可靠地适用于所有类型,包括
boost::optional

c++ boost type-traits stdoptional boost-optional
1个回答
0
投票

这是一个悬而未决的问题:https://github.com/boostorg/optional/issues/54

如果类型本身声明它是可复制分配的,则没有其他可以使用的特征。

© www.soinside.com 2019 - 2024. All rights reserved.