boostorg/fusion

boost::fusion::map or boost::fusion::map surprising behavior

Opened this issue · 2 comments

Hi!

I found surprising behavior with boost::fusion::map.
Given the following set of types:

struct Foo {};
struct Bar {};
using Child = boost::fusion::map<boost::fusion::pair<Foo, int>>;
using Parent = boost::fusion::map<boost::fusion::pair<Bar, Child>>;

The following example fails to compile:

auto example()
{
    return Parent{
        boost::fusion::make_pair<Bar>(
                boost::fusion::make_pair<Foo>(42))};
}

This can be fixed by doing:

auto example()
{
    return Parent{
        boost::fusion::pair<Bar, Child>(
                boost::fusion::make_pair<Foo>(42))};
}

While I do understand while the former fails and the latter doesn't. I do find this suprising behavior. Specially, considering the errors produced by the failing example.

There are even more confusing examples I believe (trying to disentangle my metaprograming to produce a minimal example...)

Ahaaa! Found it, the problem arises when the nested map is not the first element of the outer map. The problem seems to be related to how map_impl works via recursive inheritance in combination with some broken SFINAE. Here is a failing example that should clearly not fail...

struct Foo {};
struct Bar {};
using Child = boost::fusion::map<boost::fusion::pair<Foo, int>>;
using Parent = boost::fusion::map<
    boost::fusion::pair<Foo, float>,
    boost::fusion::pair<Bar, Child>>;

auto example()
{
    return Parent{
        boost::fusion::pair<Foo, float>{42.0f},
        boost::fusion::pair<Bar, Child>{Child{
                boost::fusion::pair<Foo, int>{42}}}};
}