首页 > 解决方案 > g++ 编译器错误:无效使用不完整类型... struct is_trivially_destructible

问题描述

我正在使用 std::variant 这是一个 C++17 功能。但据我所知,g++ 应该支持这一点。我正在使用 g++ 9.2.1 版。

总结的第一个错误是:

json20.hpp:18:48:   required from here
/usr/include/c++/9/type_traits:1235:12: error: invalid use of incomplete type ‘struct json_object’
 1235 |     struct is_trivially_destructible
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from json20.cpp:1:
json20.hpp:17:8: note: forward declaration of ‘struct json_object’
   17 | struct json_object {
      |        ^~~~~~~~~~~
In file included from /usr/include/c++/9/variant:36,
                 from json20.hpp:5,
                 from json20.cpp:1:

我正在像这样编译 json.cpp: g++ -c -std=c++17 json20.cpp

这在 Visual Studio 2017 上编译正常。虽然我必须将编译器设置为使用 c++17 标准。所以我认为它应该适用于 g++。还是我的代码有错误?

以下是源文件:

json20.hpp:

#ifndef JSON20_HPP_
#define JSON20_HPP_


#include <variant>  // type-safe union
#include <string>
#include <vector>
#include <unordered_map>
#include <iostream>

#include "json_value.hpp"

struct json_array {
    std::vector<json_value> array;
};

struct json_object {
    std::unordered_map < std::string, json_value> object;

    json_value& operator [](std::string key) {
        return object[key];
    }
};

struct json_null {

};

std::ostream& operator<< (std::ostream& os, json_value const& v);


class json20 {
public:
    /* default constructor */
    json20() {}

    /* construct json object from input stream */
    json20(std::istream& istrm, std::string& parse_status);

    /* parent node of json object */
    json_value root;

    bool insert(const json_object& object);

private:
    bool parse(std::istream& istrm, std::string& parse_status);
    json_value parse_json(std::istream& istrm, json_value& value, std::string& parse_status);
};

#endif // JSON20_HPP_

json20.cpp:

#include "json20.hpp"


std::ostream& operator<< (std::ostream& os, json_value const& v) {
    return os;
}

json20::json20(std::istream& istrm, std::string& parse_status) {

}

json_value json20::parse_json(std::istream& istrm, json_value& value, std::string& parse_status) {
    return value;
}

bool json20::parse(std::istream& istrm, std::string& parse_status) {
    return true;
}

bool json20::insert(const json_object& object) {
  return true;
}

json_value.hpp:

#ifndef JSON_VALUE_HPP_
#define JSON_VALUE_HPP_

#include "json20.hpp"

#include <variant>
#include <string>
#include <unordered_map>

// fwd declare
struct json_array;
struct json_object;
struct json_null;

typedef std::variant<double, bool, std::string, json_array, json_object, json_null> json_value;

#endif // JSON_VALUE_HPP_

测试.cpp:

#include "json20.hpp"

#include <string>
#include <iostream>
#include <sstream>
#include <unordered_map>


int main() {
    const std::string s = "my list";
    double arrayofdoubles[] = {1.0, 2.0, 3.0};
    json_array jarray;
    for (auto i : arrayofdoubles) {
        jarray.array.push_back(i);
    }

    json_object obj;
    obj.object[s] = jarray;

    json20 json;
    json.insert(obj);

    //// output to stdout
    std::ostringstream ostrm;
    ostrm << json.root;

    std::string expected("{\"my list\":[1,2,3]}");
    std::cout << json.root;
}

完整的错误消息很大,由于 stackoverflow 大小限制,我只能提供其中的一部分:

acomber@mail:~/Documents/projects/json20$ g++ -c -std=c++17 json20.cpp
In file included from /usr/include/c++/9/variant:36,
                 from json20.hpp:5,
                 from json20.cpp:1:
/usr/include/c++/9/type_traits: In instantiation of ‘struct std::is_trivially_destructible<json_object>’:
/usr/include/c++/9/type_traits:2959:25:   required from ‘constexpr const bool std::is_trivially_destructible_v<json_object>’
/usr/include/c++/9/variant:286:5:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_dtor’
/usr/include/c++/9/variant:295:4:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_move_assign’
/usr/include/c++/9/variant:677:11:   required by substitution of ‘template<class ... _Types> using _Move_assign_alias = std::__detail::__variant::_Move_assign_base<std::__detail::__variant::_Traits<_Types>::_S_trivial_move_assign, _Types ...> [with _Types = {double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null}]’
/usr/include/c++/9/variant:681:12:   required from ‘struct std::__detail::__variant::_Variant_base<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>’
/usr/include/c++/9/variant:1219:11:   [ skipping 3 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/9/bits/hashtable_policy.h:233:43:   required from ‘struct std::__detail::_Hash_node_value_base<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> > >’
/usr/include/c++/9/bits/hashtable_policy.h:264:12:   required from ‘struct std::__detail::_Hash_node<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, true>’
/usr/include/c++/9/bits/hashtable_policy.h:2027:13:   required from ‘struct std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, true> > >’
/usr/include/c++/9/bits/hashtable.h:173:11:   required from ‘class std::_Hashtable<std::basic_string<char>, std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, std::allocator<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char> >, std::hash<std::basic_string<char> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >’
/usr/include/c++/9/bits/unordered_map.h:105:18:   required from ‘class std::unordered_map<std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >’
json20.hpp:18:48:   required from here
/usr/include/c++/9/type_traits:1235:12: error: invalid use of incomplete type ‘struct json_object’
 1235 |     struct is_trivially_destructible
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from json20.cpp:1:
json20.hpp:17:8: note: forward declaration of ‘struct json_object’
   17 | struct json_object {
      |        ^~~~~~~~~~~
In file included from /usr/include/c++/9/variant:36,
                 from json20.hpp:5,
                 from json20.cpp:1:
/usr/include/c++/9/type_traits: In instantiation of ‘constexpr const bool std::is_trivially_destructible_v<json_object>’:
/usr/include/c++/9/variant:286:5:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_dtor’
/usr/include/c++/9/variant:295:4:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_move_assign’
/usr/include/c++/9/variant:677:11:   required by substitution of ‘template<class ... _Types> using _Move_assign_alias = std::__detail::__variant::_Move_assign_base<std::__detail::__variant::_Traits<_Types>::_S_trivial_move_assign, _Types ...> [with _Types = {double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null}]’
/usr/include/c++/9/variant:681:12:   required from ‘struct std::__detail::__variant::_Variant_base<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>’
/usr/include/c++/9/variant:1219:11:   required from ‘class std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>’
/usr/include/c++/9/bits/stl_pair.h:215:11:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/9/bits/hashtable_policy.h:233:43:   required from ‘struct std::__detail::_Hash_node_value_base<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> > >’
/usr/include/c++/9/bits/hashtable_policy.h:264:12:   required from ‘struct std::__detail::_Hash_node<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, true>’
/usr/include/c++/9/bits/hashtable_policy.h:2027:13:   required from ‘struct std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, true> > >’
/usr/include/c++/9/bits/hashtable.h:173:11:   required from ‘class std::_Hashtable<std::basic_string<char>, std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, std::allocator<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char> >, std::hash<std::basic_string<char> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >’
/usr/include/c++/9/bits/unordered_map.h:105:18:   required from ‘class std::unordered_map<std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >’
json20.hpp:18:48:   required from here
/usr/include/c++/9/type_traits:2959:25: error: ‘value’ is not a member of ‘std::is_trivially_destructible<json_object>’
 2959 |   inline constexpr bool is_trivially_destructible_v =
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/type_traits: In instantiation of ‘struct std::is_trivially_destructible<json_null>’:
/usr/include/c++/9/type_traits:2959:25:   required from ‘constexpr const bool std::is_trivially_destructible_v<json_null>’
/usr/include/c++/9/variant:286:5:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_dtor’
/usr/include/c++/9/variant:295:4:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_move_assign’
/usr/include/c++/9/variant:677:11:   required by substitution of ‘template<class ... _Types> using _Move_assign_alias = std::__detail::__variant::_Move_assign_base<std::__detail::__variant::_Traits<_Types>::_S_trivial_move_assign, _Types ...> [with _Types = {double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null}]’
/usr/include/c++/9/variant:681:12:   required from ‘struct std::__detail::__variant::_Variant_base<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>’
/usr/include/c++/9/variant:1219:11:   [ skipping 3 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/9/bits/hashtable_policy.h:233:43:   required from ‘struct std::__detail::_Hash_node_value_base<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> > >’
/usr/include/c++/9/bits/hashtable_policy.h:264:12:   required from ‘struct std::__detail::_Hash_node<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, true>’
/usr/include/c++/9/bits/hashtable_policy.h:2027:13:   required from ‘struct std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, true> > >’
/usr/include/c++/9/bits/hashtable.h:173:11:   required from ‘class std::_Hashtable<std::basic_string<char>, std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, std::allocator<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char> >, std::hash<std::basic_string<char> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >’
/usr/include/c++/9/bits/unordered_map.h:105:18:   required from ‘class std::unordered_map<std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >’
json20.hpp:18:48:   required from here
/usr/include/c++/9/type_traits:1235:12: error: invalid use of incomplete type ‘struct json_null’
 1235 |     struct is_trivially_destructible
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from json20.hpp:11,
                 from json20.cpp:1:
json_value.hpp:13:8: note: forward declaration of ‘struct json_null’
   13 | struct json_null;
      |        ^~~~~~~~~
In file included from /usr/include/c++/9/variant:36,
                 from json20.hpp:5,
                 from json20.cpp:1:
/usr/include/c++/9/type_traits: In instantiation of ‘constexpr const bool std::is_trivially_destructible_v<json_null>’:
/usr/include/c++/9/variant:286:5:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_dtor’
/usr/include/c++/9/variant:295:4:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_move_assign’
/usr/include/c++/9/variant:677:11:   required by substitution of ‘template<class ... _Types> using _Move_assign_alias = std::__detail::__variant::_Move_assign_base<std::__detail::__variant::_Traits<_Types>::_S_trivial_move_assign, _Types ...> [with _Types = {double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null}]’
/usr/include/c++/9/variant:681:12:   required from ‘struct std::__detail::__variant::_Variant_base<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>’
/usr/include/c++/9/variant:1219:11:   required from ‘class std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>’
/usr/include/c++/9/bits/stl_pair.h:215:11:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/9/bits/hashtable_policy.h:233:43:   required from ‘struct std::__detail::_Hash_node_value_base<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> > >’
/usr/include/c++/9/bits/hashtable_policy.h:264:12:   required from ‘struct std::__detail::_Hash_node<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, true>’
/usr/include/c++/9/bits/hashtable_policy.h:2027:13:   required from ‘struct std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, true> > >’
/usr/include/c++/9/bits/hashtable.h:173:11:   required from ‘class std::_Hashtable<std::basic_string<char>, std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >, std::allocator<std::pair<const std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char> >, std::hash<std::basic_string<char> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >’
/usr/include/c++/9/bits/unordered_map.h:105:18:   required from ‘class std::unordered_map<std::basic_string<char>, std::variant<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null> >’
json20.hpp:18:48:   required from here
/usr/include/c++/9/type_traits:2959:25: error: ‘value’ is not a member of ‘std::is_trivially_destructible<json_null>’
 2959 |   inline constexpr bool is_trivially_destructible_v =
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/type_traits: In instantiation of ‘struct std::__is_trivially_move_constructible_impl<json_object, true>’:
/usr/include/c++/9/type_traits:1185:12:   required from ‘struct std::is_trivially_move_constructible<json_object>’
/usr/include/c++/9/type_traits:2947:25:   required from ‘constexpr const bool std::is_trivially_move_constructible_v<json_object>’
/usr/include/c++/9/variant:290:5:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_move_ctor’
/usr/include/c++/9/variant:295:23:   required from ‘constexpr const bool std::__detail::__variant::_Traits<double, bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, json_array, json_object, json_null>::_S_trivial_move_assign’
/usr/include/c++/9/variant:677:11:   required by substitution of ‘template<class ... _Types> 

有趣的是,如果我用 std::map 替换 std::unordered_map ,那么它可以编译。为什么?

标签: c++g++c++17variant

解决方案


推荐阅读