построить boost::variant из проблемы с пакетом параметров

Я попытался написать функцию, которая позволяет мне построить boost::variant<> из пакета параметров. Другими словами, я пытаюсь построить один из типов boost::variant<>::types, сигнатура конструктора которого соответствует пакету, а затем преобразовать в boost::variant<>. Я по наивности написал следующее:

#!/usr/bin/env sh -vex
WARN="-W -Wall -Wextra"
INCLUDE="-isystem /c/libs/boost-trunk"
OPT="-Ofast"
g++ -x c++ - -std=gnu++1y $INCLUDE $WARN $OPT -o a <<__EOF && ./a && echo -e "\e[1;32msucceeded\e[0m" || echo -e "\e[1;31mfailed\e[0m"
#include <boost/assert.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/type_traits.hpp>

#include <type_traits>

#include <cstdlib>

struct A
{
    A() = default;
};

static_assert( std::is_constructible< A >::value,           " A()"        );
static_assert(!std::is_constructible< A, int >::value,      "!A(int)"     );
static_assert(!std::is_constructible< A, int, int >::value, "!A(int, int)");

struct B
{
    B(int) {}
};

static_assert(!std::is_constructible< B >::value,           "!B()"        );
static_assert( std::is_constructible< B, int >::value,      " B(int)"     );
static_assert(!std::is_constructible< B, int, int >::value, "!B(int, int)");

struct C
{
    C(int, int) {}
};

static_assert(!std::is_constructible< C >::value,           "!C()"        );
static_assert(!std::is_constructible< C, int >::value,      "!C(int)"     );
static_assert( std::is_constructible< C, int, int >::value, " C(int, int)");

using V = boost::variant< A, B, C >;

template< typename V,
          typename ...O >
inline constexpr
V construct(O &&... _o)
{
    using types = typename V::types;
    using predicate = std::is_constructible< boost::mpl::_1, O... >; // I think, that the problem is exactly here.
    using iter = typename boost::mpl::find_if< types, predicate >::type;
    using deduced_type = typename boost::mpl::deref< iter >::type;
#if 1
    return deduced_type(std::forward< O >(_o)...);
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
    return deduced_type{std::forward< O >(_o)...}; // second part of the question
#pragma GCC diagnostic pop
#endif

}

int main()
{
    V a = construct< V >();
    BOOST_ASSERT(a.type() == typeid(A));
    V b = construct< V >(0);
    BOOST_ASSERT(b.type() == typeid(B));
    V c = construct< V >(0, 0);
    BOOST_ASSERT(c.type() == typeid(C));
    return EXIT_SUCCESS;
}
__EOF

Он выдает прекрасный набор сообщений об ошибках, основной смысл которых, насколько я понимаю, в том, что std::is_constructible несовместима с библиотекой boost::mpl:: (точнее несовместима с заполнителями из boost::mpl::). В свою очередь, сама библиотека boost:: не содержит (якобы совместимой) черты типа boost::is_constructible.

Другая связанная с этим проблема заключается в том, чтобы иметь дело с такими классами, как struct A {}; struct B {int _1;}; struct C {int _1; int _2;};, и создавать их с помощью фигурных скобок, а не круглых скобок. Основным аспектом последней упомянутой проблемы является отсутствие признака типа, который определяет, может ли какой-либо тип быть сконструирован из некоторого набора аргументов. решение не работает с boost::mpl::.


person Tomilov Anatoliy    schedule 02.01.2014    source источник
comment
Проверить boost::mpl::lambda   -  person K-ballo    schedule 03.01.2014
comment
@K-ballo Хорошо, я попробую.   -  person Tomilov Anatoliy    schedule 03.01.2014
comment
Этот код кажется рабочим (акцент на кажется). Он использует черту is_braces_constructible в ответе, который вы связали. Я не понимаю, почему это компилируется, а ваша версия нет, поэтому я надеюсь, что вы получите хороший ответ, и мы оба сможем учиться. (Я безосновательно изменил функцию construct по совету здесь, чтобы получить менее шумную ошибку при использовании, например, V d=construct<V>(0,0,0), поэтому измените его, если хотите).   -  person llonesmiz    schedule 03.01.2014
comment
@cv_and_he Обобщение исходной проблемы в любом случае - это хорошо. Я должен принять (к счастью) этот код в качестве ответа. Что касается совместного обучения, то гораздо скорее я найду в вашем коде что-то интересное, чем наоборот. И я уже сделал.   -  person Tomilov Anatoliy    schedule 03.01.2014
comment
Предикат @cv_and_he должен быть лямбда-выражением. т.е. !!predicate::apply< T >::type::value должен иметь смысл.   -  person Tomilov Anatoliy    schedule 04.01.2014