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

标签 c++ templates template-meta-programming

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

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

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

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();}
};

此处的代码被归结为可能包含错误的程度,但在实践中效果很好。

除了它在运行时创建并复制相当长的字符串外,这些字符串表示在编译时实际上众所周知的类型。由于这是一段在嵌入式设备上运行的对性能相当敏感的代码,我想对此进行更改,以便

  1. 列表的字符串最好在编译时创建,或者,如果没有办法做到这一点,则在运行时创建一次,并且
  2. 我只需要复制指向 C 字符串的指针,因为根据 #1,字符串在内存中是固定的。
  3. 它使用我们现在坚持使用的 C++03 进行编译。

我该怎么做?

(如果这扩大了可用于此的肮脏技巧的武器库:foo 对象的名称仅由代码创建和读取,并且只有 foo_list名称字符串应该是人类可读的。)

最佳答案

您可能想查看 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;
}

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

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

关于c++ - 如何在编译时从类型创建静态字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19535290/

相关文章:

java - 此代码出现运行时错误与编译错误的原因

c++ - 为什么需要复制扣除候选作为单独的扣除指南?

C++ 在结构/类包装器中重载自动运算符

c++ - 除非我使用 cout,否则为什么我的值不正确?

c++ - 四向等价

c++ - 找不到默认构造函数来初始化 cpp 中的成员

c++ - 如何使用 C++ 模板执行正式协议(protocol)?

c++ - 在编译时将十进制转换为十六进制

c++ - 实现匿名元函数 (Lambdas) 的简便方法

c++ - 最后一行被打印两次(C++)