为什么对象不可构造?

时间:2020-11-08 23:26:00

标签: c++

我有以下代码

class MyValue
{
    std::any value;
    MyValue(std::any value)
        : value(value)
    {
    }

public:
    using ErrorType = std::string;
    using MaybeMy = std::variant<ErrorType, MyValue>;

    static MaybeMy safeWrap(std::any const &obj) noexcept
    {
        if (std::any_cast<int>(&obj) != nullptr)
            return MyValue(obj);
        else
            return ErrorType("There is some alien type");
    }
    operator std::string() const
    {
        return std::to_string(std::any_cast<int>(value));
    }
    MyValue(MyValue &&) = default;
};

int main()
{
    auto printer = [](auto &&v) { std::cout << std::string(v) << std::endl; };
    MyValue::MaybeMy as[] = {MyValue::safeWrap(10), MyValue::safeWrap("10")};
    for (auto &&v : as)
        std::visit(printer, v);
}

但是我收到与std :: variant相关的错误-MyValue不可构造。 我不明白原因。

为什么MyValue不可构造?为什么执行代码有一些限制?

编译器的输出:

[build] In file included from /usr/include/c++/9/variant:36,
[build]  from /home/created/Documents/Cpp/gstream_test/main.cpp:8:
[build] /usr/include/c++/9/type_traits: In instantiation of ‘struct std::__and_<std::is_copy_constructible<MyValue>, std::is_constructible<MyValue, const MyValue&> >’:
[build] /usr/include/c++/9/any:181:58:   required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _ValueType&&> >::value, bool>::type <anonymous>, typename std::enable_if<(! std::__is_in_place_type<_Tp>::value), bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const MyValue&; _Tp = MyValue; _Mgr = std::any::_Manager_external<MyValue>; typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _ValueType&&> >::value, bool>::type <anonymous> = <missing>; typename std::enable_if<(! std::__is_in_place_type<_Tp>::value), bool>::type <anonymous> = <missing>]’
[build] /usr/include/c++/9/type_traits:883:12:   required from ‘struct std::is_constructible<MyValue, const MyValue&>’
[build] /usr/include/c++/9/type_traits:901:12:   required from ‘struct std::__is_copy_constructible_impl<MyValue, true>’
[build] /usr/include/c++/9/type_traits:907:12:   required from ‘struct std::is_copy_constructible<MyValue>’
[build] /usr/include/c++/9/type_traits:2925:25:   required from ‘constexpr const bool std::is_copy_constructible_v<MyValue>’
[build] /usr/include/c++/9/variant:275:5:   required from ‘constexpr const bool std::__detail::__variant::_Traits<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MyValue>::_S_copy_ctor’
[build] /usr/include/c++/9/variant:1220:11:   required from ‘class std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MyValue>’
[build] /home/created/Documents/Cpp/gstream_test/main.cpp:26:5:   required from here
[build] /usr/include/c++/9/type_traits:131:12: error: incomplete type ‘std::is_copy_constructible<MyValue>’ used in nested name specifier
[build]   131 |     struct __and_<_B1, _B2>
[build]       |            ^~~~~~~~~~~~~~~~
[build] /usr/include/c++/9/type_traits: In instantiation of ‘struct std::__and_<std::is_copy_constructible<MyValue>, std::__not_<std::is_constructible<MyValue, const MyValue&> >, std::__not_<std::__is_in_place_type<MyValue> > >’:
[build] /usr/include/c++/9/type_traits:150:27:   required from ‘constexpr const bool std::__and_v<std::is_copy_constructible<MyValue>, std::__not_<std::is_constructible<MyValue, const MyValue&> >, std::__not_<std::__is_in_place_type<MyValue> > >’
[build] /usr/include/c++/9/any:192:27:   required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const MyValue&; _Tp = MyValue; _Mgr = std::any::_Manager_external<MyValue>; typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> = <missing>]’
[build] /usr/include/c++/9/type_traits:883:12:   required from ‘struct std::is_constructible<MyValue, const MyValue&>’
[build] /usr/include/c++/9/type_traits:901:12:   required from ‘struct std::__is_copy_constructible_impl<MyValue, true>’
[build] /usr/include/c++/9/type_traits:907:12:   required from ‘struct std::is_copy_constructible<MyValue>’
[build] /usr/include/c++/9/type_traits:2925:25:   required from ‘constexpr const bool std::is_copy_constructible_v<MyValue>’
[build] /usr/include/c++/9/variant:275:5:   required from ‘constexpr const bool std::__detail::__variant::_Traits<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MyValue>::_S_copy_ctor’
[build] /usr/include/c++/9/variant:1220:11:   required from ‘class std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MyValue>’
[build] /home/created/Documents/Cpp/gstream_test/main.cpp:26:5:   required from here
[build] /usr/include/c++/9/type_traits:136:12: error: incomplete type ‘std::is_copy_constructible<MyValue>’ used in nested name specifier
[build]   136 |     struct __and_<_B1, _B2, _B3, _Bn...>
[build]       |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/include/c++/9/type_traits: In instantiation of ‘constexpr const bool std::__and_v<std::is_copy_constructible<MyValue>, std::__not_<std::is_constructible<MyValue, const MyValue&> >, std::__not_<std::__is_in_place_type<MyValue> > >’:
[build] /usr/include/c++/9/any:192:27:   required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const MyValue&; _Tp = MyValue; _Mgr = std::any::_Manager_external<MyValue>; typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> = <missing>]’
[build] /usr/include/c++/9/type_traits:883:12:   required from ‘struct std::is_constructible<MyValue, const MyValue&>’
[build] /usr/include/c++/9/type_traits:901:12:   required from ‘struct std::__is_copy_constructible_impl<MyValue, true>’
[build] /usr/include/c++/9/type_traits:907:12:   required from ‘struct std::is_copy_constructible<MyValue>’
[build] /usr/include/c++/9/type_traits:2925:25:   required from ‘constexpr const bool std::is_copy_constructible_v<MyValue>’
[build] /usr/include/c++/9/variant:275:5:   required from ‘constexpr const bool std::__detail::__variant::_Traits<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MyValue>::_S_copy_ctor’
[build] /usr/include/c++/9/variant:1220:11:   required from ‘class std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MyValue>’
[build] /home/created/Documents/Cpp/gstream_test/main.cpp:26:5:   required from here
[build] /usr/include/c++/9/type_traits:150:27: error: ‘value’ is not a member of ‘std::__and_<std::is_copy_constructible<MyValue>, std::__not_<std::is_constructible<MyValue, const MyValue&> >, std::__not_<std::__is_in_place_type<MyValue> > >’
[build]   150 |     inline constexpr bool __and_v = __and_<_Bn...>::value;
[build]       |                           ^~~~~~~

我正在使用gcc 9.3

2 个答案:

答案 0 :(得分:3)

这是一个gcc错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90415

它已在gcc 8和gcc 10+中修复。

当您的构造函数使用std::any时,就会发生错误,该构造函数会尽早实例化某些类型特征并破坏内容,并在您尝试移动类型时产生硬错误(因为它也考虑了隐式转换)到std::any

一种解决方法是,不要通过添加虚拟参数使构造函数采用std::any

    MyValue(int, std::any value)
        : value(value)
    {
    }

    // ...

        return MyValue(0, obj);

或改为使用std::experimental::any / std::experimental::fundamentals_v1::any

答案 1 :(得分:-1)

班级成员的默认可访问性是私有的。由于您的构造函数位于public:声明之前,因此没有人可以构造此类的任何对象。