1

I need to initialize a boost::fusion::vector holding a boost::array as an element using initializer list. Is this possible?

boost::array<bool, 2> ary{true, false}; // works
boost::fusion::vector<int, bool> vec1{ 5, false}; // works
boost::fusion::vector<bool, std::array<bool, 2>> vec2{ false, {true, false} }; // doesn't work :(

Error:

<source>: In function 'int main()':
<source>:116:55: error: converting to 'boost::fusion::vector<int, bool>' from initializer list would use explicit constructor 'boost::fusion::vector<T>::vector(U&& ...) [with U = {int, bool}; <template-parameter-2-2> = void; T = {int, bool}]'
     boost::fusion::vector<int, bool> vec1 = { 5, false};
                                                       ^
<source>:117:81: error: no matching function for call to 'boost::fusion::vector<bool, std::array<bool, 2> >::vector(<brace-enclosed initializer list>)'
     boost::fusion::vector<bool, std::array<bool, 2>> vec2{ false, {true, false} };
                                                                                 ^
In file included from /opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector.hpp:12,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/include/vector.hpp:11,
                 from <source>:14:
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:302:9: note: candidate: 'template<class Sequence, class> constexpr boost::fusion::vector<T>::vector(Sequence&&)'
         vector(Sequence&& seq)
         ^~~~~~
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:302:9: note:   template argument deduction/substitution failed:
<source>:117:81: note:   candidate expects 1 argument, 2 provided
     boost::fusion::vector<bool, std::array<bool, 2>> vec2{ false, {true, false} };
                                                                                 ^
In file included from /opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector.hpp:12,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/include/vector.hpp:11,
                 from <source>:14:
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:289:18: note: candidate: 'template<class ... U, class> boost::fusion::vector<T>::vector(U&& ...)'
         explicit vector(U&&... u)
                  ^~~~~~
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:289:18: note:   template argument deduction/substitution failed:
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:279:35: error: mismatched argument pack lengths while expanding 'boost::is_convertible<U, T>'
                 sizeof...(U) >= 1 &&
                 ~~~~~~~~~~~~~~~~~~^~
                 fusion::detail::and_<is_convertible<U, T>...>::value &&
                 ~~~~~~             
In file included from /opt/compiler-explorer/libs/boost_1_70_0/boost/config.hpp:61,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/mpl/aux_/config/msvc.hpp:19,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/mpl/aux_/config/adl.hpp:17,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/mpl/aux_/adl_barrier.hpp:17,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/mpl/bool_fwd.hpp:17,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/mpl/bool.hpp:17,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/mpl/aux_/na.hpp:17,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/mpl/vector.hpp:19,
                 from <source>:5:
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:274:9: note: candidate: 'constexpr boost::fusion::vector<T>::vector() [with T = {bool, std::array<bool, 2>}]'
         BOOST_DEFAULTED_FUNCTION(vector(), {})
         ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:274:9: note:   candidate expects 0 arguments, 2 provided
In file included from /opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector.hpp:12,
                 from /opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/include/vector.hpp:11,
                 from <source>:14:
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:262:12: note: candidate: 'constexpr boost::fusion::vector<bool, std::array<bool, 2> >::vector(const boost::fusion::vector<bool, std::array<bool, 2> >&)'
     struct vector
            ^~~~~~
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:262:12: note:   candidate expects 1 argument, 2 provided
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:262:12: note: candidate: 'constexpr boost::fusion::vector<bool, std::array<bool, 2> >::vector(boost::fusion::vector<bool, std::array<bool, 2> >&&)'
/opt/compiler-explorer/libs/boost_1_70_0/boost/fusion/container/vector/vector.hpp:262:12: note:   candidate expects 1 argument, 2 provided
<source>:115:27: warning: unused variable 'ary' [-Wunused-variable]
     boost::array<bool, 2> ary{true, false};
                           ^~~

Using GCC 8.3, boost 1.70

Feels like I'm missing some basic understanding of how initializer lists work. Any help would be much appreciated.

anni
  • 338
  • 2
  • 12
  • I realized that it works with boost 1.53 but it fails with boost 1.70 :( Could this be a regression in boost library? – anni Jul 01 '22 at 19:25

1 Answers1

1

It's a language limitation on deducing nested brace-initializers.

The best version I can come up with using C++17 CTAD is e.g.

Live On Compiler Explorer

#include <array>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/vector.hpp>

int main() {
  auto vec = boost::fusion::make_vector(false, std::array{true, false});
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for your reply! It seems to work with boost 1.53 but not with boost 1.70 so it feels like its related to boost library rather than language limitation. – anni Jul 01 '22 at 19:31
  • 2
    That changes the question considerably, which I can't really help. Most likely the change is that Fusion started to support more things which makes the constructor non-deducible/ambiguous. That's not really regressing, more like new features/trade-offs – sehe Jul 01 '22 at 20:43