1

How can I make the following Boost Fusion struct?

#include <array>
#include <boost/fusion/include/define_struct_inline.hpp>

BOOST_FUSION_DEFINE_STRUCT_INLINE(
  MyStruct,
  (std::array<int, 3>, foo)
)

This fails to compile (GCC 4.8.1 and Boost 1.53) because std::array<int, 3> is interpreted as 2 arguments instead of 1.

Note that I am NOT asking about the special case shown above (it's just an example). This particular problem has the trivial solution of just using typedef std::array<int, 3> Int3Array;.

I am asking about the general problem of using types with multiple template arguments separated by commas as a type in the list of fields of a Boost Fusion struct. Eventually, I want to use a template Boost Fusion struct where I cannot define typedefs in advance. For example, I might want to do something like this:

BOOST_FUSION_DEFINE_TPL_STRUCT_INLINE(
  (A)(B)(C),
  MyAdvancedStruct,
  (A<B, C>, bar)
)
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Flecto
  • 315
  • 2
  • 7

2 Answers2

0

A workaround that works could be

BOOST_FUSION_DEFINE_STRUCT_INLINE(
  MyStruct,
  (decltype(std::array<int, 3>()), foo)
)

Of course to make it /generally/ applicable

BOOST_FUSION_DEFINE_STRUCT_INLINE(
MyStruct,
(boost::remove_reference<decltype(std::declval<std::array<int, 3>>())>::type, foo)
)

Which seems to call for another macro... but, oh wait :) BOOST_PP_COMMA seems the better choice.

Proof of concept: http://coliru.stacked-crooked.com/a/f8b407b810fcfdc0

sehe
  • 374,641
  • 47
  • 450
  • 633
  • This is great, thank you! Do I understand correctly that your general solution (with std::declval etc) is needed if the type does not have a default constructor (i.e. decaltype(Type()) would not work)? If so, this situation will never come up, because if one uses a type without a default constructor in a Boost Fusion struct, one gets a compile time error when Boost tries to implement the default constructor for the struct... But it's good that you mentioned that general solution for completeness. – Flecto May 08 '14 at 23:25
  • How could I make this work with BOOST_PP_COMMA? `(std::array, foo)` doesn't work. – Flecto May 08 '14 at 23:27
  • @Flecto aha. Appears you are right. Well then, my workaround gets some merit, then. I hope your classes are default constructible, so you don't need the horrible `declval<>` dance – sehe May 08 '14 at 23:34
0

If you can't use a typedef or using declaration, try using Boost.IdentityType like this:

#include <array>
#include <boost/fusion/include/define_struct_inline.hpp>
#include <boost/utility/identity_type.hpp>

BOOST_FUSION_DEFINE_STRUCT_INLINE(
  MyStruct,
  (typename BOOST_IDENTITY_TYPE((std::array<int, 3>)), foo)
)

int main()
{
    MyStruct x;
    static_assert(boost::is_same<decltype(x.foo), std::array<int, 3> >::value, "yup");
}

See Coliru live demo.

Marek Kurdej
  • 1,459
  • 1
  • 17
  • 36