使用 boost mpl inserter 迭代器的意外结果

发布于 2024-11-15 19:33:27 字数 1377 浏览 3 评论 0原文

我原以为以下会给出相同的结果:

namespace mpl = boost::mpl;

template<int from, int to>
struct
make_vector1
 : mpl::copy<
     mpl::range_c<int,from,to>, 
     mpl::inserter< 
       mpl::vector<>,
       mpl::push_back<mpl::placeholders::_1,
              mpl::placeholders::_2 // <- Copy int_ types
             >
       > 
     >  
{};

template<int from, int to>
struct
make_vector2 
 : mpl::copy<
     mpl::range_c<int,from,to>, 
     mpl::inserter< 
       mpl::vector<>,
       mpl::push_back<mpl::placeholders::_1,
              mpl::int_<mpl::placeholders::_2::value> // <- Alternative?
              >
       > 
     >
{};

但他们没有。

int
main  (int ac, char **av)
{
  typedef make_vector1<0,3>::type v1;
  typedef make_vector2<0,3>::type v2;

  //returns 0, as I would expect
  std::cout<<"I1 = "<<mpl::at<v1,mpl::int_<0> >::type::value <<std::endl;

  //returns 2, which has me stumpted.
  std::cout<<"I2 = "<<mpl::at<v2,mpl::int_<0> >::type::value <<std::endl;
}

知道这是怎么回事吗?

我想使用第二种方法来构造 Example 类型的 mpl::vector,其中:

template<int i>
struct Example : mpl::int_<i>
{};

但我无法让它工作。

非常感谢

I had expected the following to give the same result:

namespace mpl = boost::mpl;

template<int from, int to>
struct
make_vector1
 : mpl::copy<
     mpl::range_c<int,from,to>, 
     mpl::inserter< 
       mpl::vector<>,
       mpl::push_back<mpl::placeholders::_1,
              mpl::placeholders::_2 // <- Copy int_ types
             >
       > 
     >  
{};

template<int from, int to>
struct
make_vector2 
 : mpl::copy<
     mpl::range_c<int,from,to>, 
     mpl::inserter< 
       mpl::vector<>,
       mpl::push_back<mpl::placeholders::_1,
              mpl::int_<mpl::placeholders::_2::value> // <- Alternative?
              >
       > 
     >
{};

But they do not.

int
main  (int ac, char **av)
{
  typedef make_vector1<0,3>::type v1;
  typedef make_vector2<0,3>::type v2;

  //returns 0, as I would expect
  std::cout<<"I1 = "<<mpl::at<v1,mpl::int_<0> >::type::value <<std::endl;

  //returns 2, which has me stumpted.
  std::cout<<"I2 = "<<mpl::at<v2,mpl::int_<0> >::type::value <<std::endl;
}

Any idea what is going on here?

I want to use the second method to construct a mpl::vector of Example types, where:

template<int i>
struct Example : mpl::int_<i>
{};

but I cannot get it working.

Many thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

软甜啾 2024-11-22 19:33:27

您得到 2,因为 _2 上的 ::value 被定义为 2(占位符索引)。出于显而易见的原因,MPL 没有在占位符上定义 :: ,因此您不能直接执行此操作。

现在,访问 mpl::range_c 中的元素已经为您提供了 mpl::int_ 正如您所注意到的,因此无需尝试提取数值以将其放回去。 mpl 序列迭代的抽象会为你做这件事。

对于您的实际使用,您可以使用元函数接受 mpl::int_ 并返回您的示例。您必须明白,整数类型无法完成适当的通用元编程或元 lambda 函数,因此 mpl::int_ 抽象:

#include <boost/mpl/at.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/push_back.hpp>

namespace mpl = boost::mpl;

template<int I> struct Example : boost::mpl::int_<I> 
{
  static void foo() { std::cout << "**" << I << "**\n";}
};

template<class T> struct make_example
{
  typedef Example<T::value> type;
};

template<int from, int to>
struct
make_vector2 
 : mpl::copy<
     mpl::range_c<int,from,to>, 
     mpl::inserter< 
       mpl::vector<>,
       mpl::push_back<mpl::placeholders::_1,
              make_example<mpl::placeholders::_2> // <- Alternative?
              >
       > 
     >
{};

int main(int ac, char **av)
{
  typedef make_vector2<0,3>::type v2;

  mpl::at<v2,mpl::int_<0> >::type::foo();
}

我添加 foo() 只是为了评估我们在调用 at 后进入正确的类类型。

让我们回顾一下:

  • 积分模板参数是不可靠的,这就是 MPL 使用 int_ 的原因。每个整型常量序列实际上已经返回 int_ 以保持抽象级别。
  • 占位符有一个 ::value 用于内部目的,因此您的初始结果
  • 任何元函数都可以通过使用占位符实例化来转换为 lambda。

You get a 2 because ::value on _2 is defined to be 2 (the placeholder index). MPL don't define :: on placeholders for obvious reason so you can not directly do this.

Now, accessing an element in a mpl::range_c already gives you an mpl::int_ as you noticed so there is no need to try to extract the numerical value to put it back. The abstraction of the iteration over mpl sequence do it for you.

For your actual use, case you can use a meta-function taking a mpl::int_ and returning your Example. You have to grasp that no proper generic meta-programming nor meta-lambda function can be done with integral type, thus the mpl::int_ abstraction :

#include <boost/mpl/at.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/push_back.hpp>

namespace mpl = boost::mpl;

template<int I> struct Example : boost::mpl::int_<I> 
{
  static void foo() { std::cout << "**" << I << "**\n";}
};

template<class T> struct make_example
{
  typedef Example<T::value> type;
};

template<int from, int to>
struct
make_vector2 
 : mpl::copy<
     mpl::range_c<int,from,to>, 
     mpl::inserter< 
       mpl::vector<>,
       mpl::push_back<mpl::placeholders::_1,
              make_example<mpl::placeholders::_2> // <- Alternative?
              >
       > 
     >
{};

int main(int ac, char **av)
{
  typedef make_vector2<0,3>::type v2;

  mpl::at<v2,mpl::int_<0> >::type::foo();
}

I added foo() just to assess we go into the proper class type after calling at.

So let's recap :

  • integral template parameters are dodgy and that's why MPL use int_. Every integral constant sequence actually return int_ already to keep the level of abstraction.
  • placeholders have a ::value for internal purpose, hence your initial result
  • Any meta-function an be turned into a lambda by instantiating it with a placeholders.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文