C++ 构造boost::参数包问题的变体

C++ 构造boost::参数包问题的变体,c++,boost,typetraits,boost-variant,C++,Boost,Typetraits,Boost Variant,我试图编写一个函数,允许我从参数包构造一个boost::variant。换句话说,我试图构造一个boost::variant::typestype,其构造函数的签名与包匹配,然后转换为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 $

我试图编写一个函数,允许我从参数包构造一个
boost::variant
。换句话说,我试图构造一个
boost::variant::types
type,其构造函数的签名与包匹配,然后转换为
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
#/usr/bin/env sh-vex
WARN=“-W-Wall-Wextra”
INCLUDE=“-isystem/c/libs/boost trunk”
OPT=“-Ofast”
G++-XC++(STD= GNU+1Y$)包含$$$OPT-O:::“!A(int));
静态断言(!std::is_-constructible::value,“!A(int,int)”;
结构B
{
B(int){}
};
静态断言(!std::is_可构造::值,“!B()”;
静态断言(std::是可构造的::值,“B(int)”;
静态断言(!std::is_constructible::value,“!B(int,int)”;
结构C
{
C(int,int){}
};
静态断言(!std::is_可构造::值,“!C()”;
静态断言(!std::is_可构造::值,“!C(int)”;
静态断言(std::是可构造的::值,“C(int,int)”;
使用V=boost::variant;
模板
内联常量表达式
V构造(O&&…_O)
{
使用types=typename V::types;
使用predicate=std::is_constructible;//我认为问题就在这里。
使用iter=typename boost::mpl::find_if::type;
使用导出的类型=类型名boost::mpl::deref::type;
#如果1
返回类型(std::forward(\u O)…);
#否则
#pragma GCC诊断推送
#pragma GCC诊断已忽略“-Wmissing字段初始值设定项”
返回导出的_类型{std::forward(_O)…};//问题的第二部分
#pragma-GCC-diagnostic-pop
#恩迪夫
}
int main()
{
va=构造();
BOOST_断言(a.type()==typeid(a));
V b=构造(0);
BOOST_断言(b.type()==typeid(b));
V c=构造(0,0);
BOOST_断言(c.type()==typeid(c));
返回退出成功;
}
__EOF
它生成了一个可爱的错误消息包,据我所知,其基本含义是
std::is_constructible
boost::mpl::
库不兼容(或者更确切地说,与
boost::mpl:
中的占位符不兼容)。反过来,
boost::
库本身不包含(假定兼容的)
boost::是可构造的
类型特征


另一个相关的问题是处理类,如
struct A{};结构B{int_1;};结构C{int_1;int_2;}并通过大括号而不是圆括号来构造它们。最后提到的问题的主要方面是缺少类型特征,它可以推断是否可以从一些参数包构造某些类型。这个不适用于
boost::mpl::

检查
boost::mpl::lambda
@K-ballo好的,我会试试。似乎有效(强调似乎有效)。它在链接的答案中使用trait
is_brakes_constructible
。我不明白为什么会编译而你的版本不会,所以我希望你能得到一个好的答案,我们都可以学习。(我按照建议“无偿”更改了函数
construct
,以在使用例如
vd=construct(0,0,0)
时获得一个噪音较小的错误,因此,如果您愿意,请将其更改回原来的函数)。@cv\u和\u不管怎样,对原始问题的概括是一件好事。我不得不(幸运地)把那个代码作为答案。至于一起学习,我更可能在您的代码中发现一些有趣的东西,而不是相反。我已经做了。@cv_和_他应该是。也就是说,
!!谓词::apply::type::value
应该有意义。