如何在编译时从类型创建静态字符串

sbi*_*sbi 10 c++ templates template-meta-programming

我有一堆有名字的类型.(它们有更多功能,但为了讨论起见,只有名称是相关的.)这些类型及其名称是在编译时使用宏设置的:

#define DEFINE_FOO(Foo_)                        \
    struct Foo_ : public foo_base<Foo_> {       \
      static char const* name() {return #Foo_;} \
    }
Run Code Online (Sandbox Code Playgroud)

然后将这些类型组合在编译时列表(经典的简单递归编译时列表)中,我需要通过连接其对象的名称来创建列表的名称:

template<class Foo, class Tail = nil>
struct foo_list {
  static std::string name_list() {return Foo::name() + "-" + Tail::name();}
};
template<class Foo>
struct foo_list<Foo,nil> {
  static std::string name_list() {return Foo::name();}
};
Run Code Online (Sandbox Code Playgroud)

代码在这里归结为它可能包含错误的程度,但实际上这很好用.

除了它在运行时创建然后复制相当长的字符串,这些字符串表示在编译时实际上是众所周知的类型.由于这是一个在嵌入式设备上运行的性能相当敏感的代码,我想改变这一点

  1. 列表的字符串理想地是在编译时创建的,或者,如果没有办法在运行时创建它,并且
  2. 我只需要复制一个指向C字符串的指针,因为根据#1,字符串在内存中是固定的.
  3. 这与C++ 03一起编译,我们现在一直坚持使用它.

我怎样才能做到这一点?

(如果这扩大了可用于此的脏技巧:foo只能通过代码创建和读取对象的foo_list名称,并且只有名称字符串应该是人类可读的.)

Nim*_*Nim 4

您可能想看看 boost 的mpl::string. 我的咖啡喝完后可以遵循的例子......

编辑:所以咖啡已经开始了......:)

#include <iostream>

#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/string.hpp>
#include <boost/mpl/vector.hpp>

namespace mpl = boost::mpl;

struct foo
{
  typedef mpl::string<'foo'> name;
};

struct bar
{
  typedef mpl::string<'bar'> name;
};

struct gah
{
  typedef mpl::string<'gah'> name;
};

namespace aux
{

template <typename string_type, typename It, typename End>
struct name_concat
{
  typedef typename mpl::insert_range<string_type, typename mpl::end<string_type>::type, typename mpl::deref<It>::type::name>::type base;
  typedef typename aux::name_concat<base, typename mpl::next<It>::type, End>::name name;
};

template <typename string_type, typename End>
struct name_concat<string_type, End, End>
{
  typedef string_type name;
};

}

template <typename ...Types>
struct type_list
{
  typedef mpl::string<> base;
  typedef mpl::vector<Types...> type_seq;
  typedef typename aux::name_concat<base, typename mpl::begin<type_seq>::type, typename mpl::end<type_seq>::type>::name name;
};

int main(void)
{
  typedef typename type_list<foo, bar, gah>::name tlist_name;
  std::cout << mpl::c_str<tlist_name>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我相信您有足够的能力根据您的情况调整上述内容。注意:您必须忽略多字符常量警告...

还有一些注意事项:传递给的多字符常量mpl::string不能超过 4 个字符,因此,必须将其分块(或由单个字符构造),因此可以是长字符串,mpl::string<'this', ' is ', 'a lo', 'ng s', 'trin', 'g'>如果无法做到这一点,那么上面的方法将不起作用..:/