我很难理解以下简单程序为何无法编译。我有一个可变参数的模板类(下面是my_type),我想用它来转换mpl vector 。以下代码段会导致编译错误“/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:38:19:在'template'关键字后使用'apply'并不引用模板”。

#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>

template <class... T>
struct my_type{};

using namespace boost::mpl;

using test_type = vector<int, double>;

// expected result is vector< my_type<int>, my_type<double> >
using result_type = transform< test_type, my_type<_> >::type;

int main() {

}

使my_type接受单个模板参数可以很好地工作,但是我想了解为什么可变参数版本不起作用。先感谢您!

最佳答案

transform期望的第二个参数是您未传递的一元运算。

在您的情况下,my_type不是mpl期望的metafunction,因为它正在使用可变参数列表。

在最简单的情况下,metafunction公开type typedef或ststic bool value。例如:

template <typename T>
struct add_pointer {
    using type = T*;
};

注意add_pointer如何转换提供的模板参数。这是unary操作的一个示例,因为它仅使用一个模板参数T

在您的示例中,my_type纯粹是一种类型,不能用作元函数或操作,因为它不满足metafunction元功能所要求的transform标准,后者具有type字段来指示转换后的类型。

在某些情况下,如下面的metafunction部分中所述,将简单的模板类型转换为Detailed Reasoning

Doc引用:http://www.boost.org/doc/libs/1_31_0/libs/mpl/doc/ref/Reference/transform.html

码:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/equal.hpp>

#include <type_traits>
#include <typeindex>
#include <iostream>

template <class... T>
struct my_type{};

using namespace boost::mpl;

using test_type = vector<int, double>;

template <typename T>
struct add_my_type {
    using type = my_type<T>;
};

using result_type = typename transform< test_type, add_my_type<_1> >::type;

int main() {
    static_assert (equal<result_type, vector< my_type<int>, my_type<double> >>::value, "Nope!!");

    std::cout << typeid(result_type).name() << std::endl;
}

LIVE DEMO

详细原因

上面解释的原因很简单,应该足以回答问题。但是,让我尽可能地深入细节。

免责声明:我不是boost::mpl的专家。

根据OP的以下注释,如果我们将my_type更改为:
template <class T>
struct my_type{};

但是,这与我之前提到的不太吻合,即operation需要type标识符。因此,让我们看看mpl在做什么:
struct transform看起来像:
template<
  typename Seq1 = mpl::na
, typename Seq2OrOperation = mpl::na
, typename OperationOrInserter = mpl::na
, typename Inserter = mpl::na
>
struct transform {
  boost::mpl::eval_if<
        boost::mpl::or_<
            boost::mpl::is_na<OperationOrInserter>,
            boost::mpl::is_lambda_expression<my_type<mpl_::arg<1> > >,
            boost::mpl::not_<boost::mpl::is_sequence<my_type<mpl_::arg<1> > > >,
            mpl_::bool_<false>,
            mpl_::bool_<false>
        >,
        boost::mpl::transform1<
            boost::mpl::vector<int, double>,
            my_type<mpl_::arg<1>>,
            mpl_::na
        >,
        boost::mpl::transform2<boost::mpl::vector<int, double>,
            my_type<mpl_::arg<1> >,
            mpl_::na, mpl_::na>
        >

};

这里要看的重要部分是is_lambda_expression元函数,该函数基本检查您的Operation是否满足metafunction的要求。

在应用了一些繁琐的宏和模板机制以及专业之后,上面的检查综合如下:
template<
      typename IsLE, typename Tag
    , template< typename P1 > class F
    , typename L1
    >
struct le_result1
{
    typedef F<
          typename L1::type
        > result_;

    typedef result_ type;
};

在这里,F是您的my_type,而L1placeholder。因此,从本质上讲,以上结构只不过是我在初始响应中显示的add_my_type

如果到目前为止我是正确的,le_result1是将在您的operation上执行的sequence

09-10 05:13
查看更多