Я пытаюсь определить и посетить «рекурсивный» boost::variant
используя класс incomplete обертку и std::vector
как мои методы косвенности. Моя реализация работает с libstdC++, но не с libC++.Рекурсивного определение и посещение `подталкивания :: variant` с помощью` зОго :: VECTOR`, содержащего неполный типа - libstdC++ против LibC++
Это так я определяю мой вариант:
struct my_variant_wrapper;
using my_variant_array = std::vector<my_variant_wrapper>; // <- indirection here
using my_variant = boost::variant<int, my_variant_array>;
struct my_variant_wrapper
{
my_variant _v;
template <typename... Ts>
my_variant_wrapper(Ts&&... xs) : _v(std::forward<Ts>(xs)...) { }
};
Я использую std::vector
ввести окольные (так что динамическое распределение будет препятствовать my_variant
иметь бесконечный размер).
Я вполне уверен, что я имею право использовать std::vector<my_variant_wrapper>
, где my_variant_wrapper
является incomplete type, из-за paper N4510("Minimal incomplete type support for standard containers"):
Документ был утвержден, в соответствии с WG21's 2015 page.
Характеристики всегда поддерживались в libstdC++, в соответствии с this page.
Это было реализовано в libC++ 3.6, в соответствии с this page.
Я тогда посещение вариант следующим образом:
struct my_visitor
{
void operator()(int x) const { }
void operator()(const my_variant_array& arr) const
{
for(const auto& x : arr)
boost::apply_visitor(*this, x._v);
}
};
int main()
{
my_variant v0 = my_variant_array{
my_variant{1}, my_variant{2}, my_variant_array{
my_variant{3}, my_variant{4}
}
};
boost::apply_visitor(my_visitor{}, v0);
}
A minimal complete example is available on coliru.
Я использую следующие флаги:
-std = С ++ 1z -Wall -Wextra -Wpedantic
BOOST_VERSION
вычисляет106100
.
Код:
компилируется и работает по назначению на:
г ++ (протестированных версиях: 6.1 и 7) с libstdC++.
clang ++ (проверенные версии: 3.8), с libstdC++.
(в качестве бонуса, он также работает с
std::variant
путем внесения соответствующих изменений!)
Не удается скомпилировать на:
- лязгом ++ (протестированных версий : 3,8, 4), с libC++.
Это ошибка я получаю во время компиляции на лязг ++ с LibC++:
In file included from prog.cc:2:
In file included from /usr/local/boost-1.61.0/include/boost/variant.hpp:17:
/usr/local/boost-1.61.0/include/boost/variant/variant.hpp:1537:28: error: no matching member function for call to 'initialize'
initializer::initialize(
~~~~~~~~~~~~~^~~~~~~~~~
/usr/local/boost-1.61.0/include/boost/variant/variant.hpp:1692:9: note: in instantiation of function template specialization 'boost::variant<int, std::__1::vector<my_variant_wrapper, std::__1::allocator<my_variant_wrapper> > >::convert_construct<my_variant_wrapper>' requested here
convert_construct(operand, 1L);
^
prog.cc:15:38: note: in instantiation of function template specialization 'boost::variant<int, std::__1::vector<my_variant_wrapper, std::__1::allocator<my_variant_wrapper> > >::variant<my_variant_wrapper>' requested here
my_variant_wrapper(Ts&&... xs) : _v(std::forward<Ts>(xs)...) { }
^
/usr/local/libcxx-head/include/c++/v1/memory:1783:31: note: in instantiation of function template specialization 'my_variant_wrapper::my_variant_wrapper<my_variant_wrapper &>' requested here
::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
^
/usr/local/libcxx-head/include/c++/v1/memory:1694:18: note: in instantiation of function template specialization 'std::__1::allocator<my_variant_wrapper>::construct<my_variant_wrapper, my_variant_wrapper &>' requested here
{__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
^
...
The full error is available on wandbox.
Почему код не компиляции с LIBC++?(Может быть, это дефект в реализации LibC++ ы N4510, который должен сообщать?)
ошибка, кажется, предполагает, что вариант не удается обнаружить то, что члены должны быть инициализированы, но я честно не мог сделать много смысла из этого. Меня также смущает тот факт, что с использованием libstdC++(с той же форсированной версией) работает должным образом.
Awesome, спасибо! [Он компилируется с ** libC++ **] (http://melpon.org/wandbox/permlink/TCBfoFPrEZHFE8G0) при ограничении. Я все еще озадачен тем, почему эта ошибка возникает только с libC++, хотя, может быть, вы прокомментируете это? –
@ VittorioRomeo Просто потратил некоторое время на рытье - см. Править. –
Итак, вектор libC++ пытается скопировать-построить векторные элементы, используя ссылку на константу lvalue, тогда как libstdC++ передает ссылку const lvalue. Поскольку libC++ использует неконстантную ссылку, он выбирает конструктор шаблонов вместо конструктора копирования. – EricWF