4

スコープ付き Boost Phoenix ステートメント内で使用されるローカル変数の型を取得するにはどうすればよいですか? Phoenix と Proto を使用して、Phoenix 式のさまざまな側面を抽出できます。たとえば、次のコードはアリティ (3) を公開します。タグタイプ (lambda_actor); Phoenix ラムダ式の子 2 タグ タイプ (shift_left):

#include <boost/proto/proto.hpp>
#include <boost/phoenix.hpp>

namespace proto   = boost::proto;
namespace phoenix = boost::phoenix;
using namespace phoenix::local_names;

struct Foo { const char str[6] = " Ok.\n"; };

int main(int argc, char *argv[])
{
  auto f = phoenix::lambda(_a = 17, _b = Foo()) [
    std::cout << _a << phoenix::bind(&Foo::str,_b)
  ];

  typedef typename proto::tag_of<decltype(                  f )>::type tag;
  typedef typename proto::tag_of<decltype(proto::child_c<2>(f))>::type tagc;
  static_assert(proto::arity_of<decltype(f)>::value==3,"");
  static_assert(std::is_same<tag,  phoenix::tag::lambda_actor>::value,"");
  static_assert(std::is_same<tagc, proto::tag::shift_left>::value,"");

  return 0;
}

ローカル変数の型を取得するにはどうすればよいですか。この例では:_aおよび_b?

4

1 に答える 1

1

あなたが興味を持っているタイプはintとであると想定していFooます。これがあなたの求めているものでない場合は、この回答を無視してください。ドキュメントを見てみると、これらの型を取得する簡単な方法を見つけることができませんでした。しかし、格納されている proto 式の型をf見るとintFoo最初の子内のアクターのベクトルで見つけることができます。最終的に興味深い型に到達するために必要な手順は、出力で確認でき、その後、必要な機能を実行するメタ関数を簡単に作成できます。この単純なケースでget_local_typeは、インデックスを使用して問題の型にアクセスします。名前で ( を使用して) アクセスしたい場合は_a、 のデータを使用して名前に関連付けられたインデックスを取得できるはずです。map_local_index_to_tupleラムダ式の 2 番目の子。ここphoenix::detail::get_indexで定義されているものを使用すると、実装も非常に簡単です。このメタ関数は、最初の引数として上記のマップを想定し、2 番目の引数として情報を取得するプレースホルダーの型 (より具体的には が必要であり、プレースホルダーの型で使用して取得できます) を想定しています。get_local_type_from_namephoenix::detail::local<phoenix::local_names::_a_key>proto::result_of::value

#include <iostream>
#include <typeinfo>
#include <string>
#include <cxxabi.h>
#include <type_traits>

#include <boost/proto/proto.hpp>
#include <boost/phoenix.hpp>

namespace proto   = boost::proto;
namespace phoenix = boost::phoenix;
using namespace phoenix::local_names;

namespace fusion = boost::fusion;

struct Foo { const char str[6] = " Ok.\n"; };



std::string demangle(const char* mangledName) {
    int status;
    char* result = abi::__cxa_demangle(mangledName, nullptr, nullptr, &status);
    switch(status) {
    case -1:
        std::cerr << "Out of memory!" << std::endl;
        exit(1);
    case -2:
        return mangledName;
    case -3: // Should never happen, but just in case?
        return mangledName;
    }
    std::string name = result;
    free(result);
    return name;
}


template <typename Lambda, int N>
struct get_local_type
{
    typedef typename proto::result_of::value<typename proto::result_of::child_c<Lambda,0>::type >::type vector_of_locals_type;
    typedef typename proto::result_of::value<typename fusion::result_of::at_c<vector_of_locals_type,N>::type >::type ref_type;
    typedef typename std::remove_reference<ref_type>::type type;
};

template <typename Lambda, typename Arg>
struct get_local_type_from_name
{
    typedef typename proto::result_of::value<Arg>::type local_name;
    typedef typename proto::result_of::value<typename proto::result_of::child_c<Lambda,1>::type >::type map_type;
    typedef typename phoenix::detail::get_index<map_type,local_name>::type index;
    typedef typename get_local_type<Lambda,index::value>::type type;

};



int main(int argc, char *argv[])
{
  auto f = phoenix::lambda(_b = 17, _a = Foo()) [
    std::cout << _b << phoenix::bind(&Foo::str,_a)
  ];

  std::cout << std::endl << "This is the whole lambda expression:" << std::endl;
  std::cout << std::endl << demangle(typeid(f).name()) << std::endl;
  std::cout << std::endl << "Take the first child:" << std::endl;
  std::cout << std::endl << demangle(typeid(proto::child_c<0>(f)).name()) << std::endl;
  std::cout << std::endl << "Then its value (this is a vector that contains the types you want):" << std::endl;
  std::cout << std::endl << demangle(typeid(proto::value(proto::child_c<0>(f))).name()) << std::endl;
  std::cout << std::endl << "Take the first element of that vector:" << std::endl;
  std::cout << std::endl << demangle(typeid(fusion::at_c<0>(proto::value(proto::child_c<0>(f)))).name()) << std::endl;
  std::cout << std::endl << "Take the value of that element:" << std::endl;
  std::cout << std::endl << demangle(typeid(proto::value(fusion::at_c<0>(proto::value(proto::child_c<0>(f))))).name()) << std::endl;


  typedef typename proto::tag_of<decltype(                  f )>::type tag;
  typedef typename proto::tag_of<decltype(proto::child_c<2>(f))>::type tagc;
  static_assert(proto::arity_of<decltype(f)>::value==3,"");
  static_assert(std::is_same<tag,  phoenix::tag::lambda_actor>::value,"");
  static_assert(std::is_same<tagc, proto::tag::shift_left>::value,"");

  typedef typename get_local_type<decltype(f),0>::type type_of_1st;
  typedef typename get_local_type<decltype(f),1>::type type_of_2nd;
  typedef typename get_local_type_from_name<decltype(f),_a_type>::type type_of_a;
  typedef typename get_local_type_from_name<decltype(f),decltype(_b)>::type type_of_b;
  static_assert(std::is_same<type_of_1st,int>::value,"");
  static_assert(std::is_same<type_of_2nd,Foo>::value,"");
  static_assert(std::is_same<type_of_a,Foo>::value,"");
  static_assert(std::is_same<type_of_b,int>::value,"");


  return 0;
}
于 2013-05-24T13:50:25.913 に答える