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

时间:2014-02-13 23:22:31

标签: c++ c++11 template-meta-programming lambda

我正在使用模板元编程来处理字符串操作库。我使用C ++ 11通用常量表达式like in this article在编译时访问原始字符串元素,生成一个包含字符的类型列表,这是元编程库可以处理的类型:

template<typename INDEX>
struct transform_function
{
    using result = tml::character<"hello world!"[INDEX::value]>;
};

//tml::for_each returns the set of applications of each element of the specified
//interval on the specified metafunction. In other words, generates a typelist
//which contains each character of the string:

using str = tml::for_each<tml::make_size_t_forward_iterator<0> , 
                          tml::make_size_t_forward_iterator<sizeof("hello world!")> ,
                          transform_function>;

using hello2 = tml::concat<str,str>; //hello2 holds "hello world!hello world!"

我编写了一个宏,它从指定的原始字符串生成上面的代码,并用指定的名称命名。例如:

TURBO_STRING_VARIABLE( hello , "hello " );
TURBO_STRING_VARIABLE( world , "world!" );

using hello_world = tml::concat<hello,world>;

现在我想要的是这样一个宏来生成一个有用的字符串,就像这样:

template<typename STRING>
struct to_upper{ ... };

using HELLO_WORLD = typename to_upper<hello_world>::result; //OK, holds "HELLO WORLD!"
using HELLO = typename to_upper<ANONYMOUS_STRING("hello")>; //HELLO

我的for_each方法不起作用,因为我无法在模板argumment传递的上下文中定义类型,但我在想一种lambda元函数将转换函数直接写入argumment。登记/> 我知道Boost.MPL有这样的东西使用占位符,但我认为不能在这个上下文中使用,因为我在一个与模板无关的上下文中使用参数(数组的索引运算符)并且无法应用占位符技巧。

还有其他方法可以实现这一目标吗?

1 个答案:

答案 0 :(得分:1)

在本文中,描述了使用最大字符串长度来实现ANONYMOUS_STRING的方法。这应该是一般没问题的。只需将100作为最大值,并在字符串较长时断言。用户可以通过连接较短的字符串来创建更长的字符串。有100个字符,你通常有很长的行,无论如何都需要打破它们(考虑终端窗口中源代码的可读性)。

concat<
  ANONYMOUS_STRING("Hello "),
  ANONYMOUS_STRING("World "),
  ANONYMOUS_STRING("!")
>

使用此代码,可以以可读的方式生成更长的字符串。

一般问题是字符串文字不能是模板参数,你不能在你想到的点内部创建一个类:

template<class T>
struct f{};

using g=f<struct { /* some types and data */ }>; // does not work

方法是在这一点实例化另一个模板:

using g=f<std::integral_constant<char, 'x'>>; // does work

所以我认为你必须创建一个宏,对于小字符串来说是大的,对于大字符串来说是小的。这就是Abel Sinkovics和Dave Abrahams描述它的方式。一个很好的效果是你可以用更好的TURBO_STRING_VARIABLE( hello , "hello " );

替换using hello = ANONYMOUS_STRING("hello");