【问题标题】:C++ template string concatenationC++ 模板字符串连接
【发布时间】:2011-06-09 07:01:25
【问题描述】:

我正在尝试定义一些这样的可变参数模板:

typedef const char CCTYPE[];
template<CCTYPE X, CCTYPE... P> struct StringConcat { ... };

这样我就可以这样写:

char foo[] = "foo"; char bar[] = "bar";
std::cout << StringConcat<foo, bar>;

它打印了foobar。 如果在 C++0x 中可行,我该怎么做?

我真正的兴趣是使用 c++ 模板解决 FizzBuzz 问题,我找到了一个解决方案 here 使用模板将 int 转换为 char[]。

【问题讨论】:

  • 将这两个字符串作为常规参数传递有什么问题?
  • 定期连接字符串不是问题,我想只使用模板来做到这一点,我添加了一段描述我正在做的事情。

标签: c++ string templates metaprogramming c++11


【解决方案1】:
#include <boost/mpl/string.hpp>
#include <boost/mpl/insert_range.hpp>
#include <boost/mpl/end.hpp>
#include <iostream>

using namespace boost;

template < typename Str1, typename Str2 >
struct concat : mpl::insert_range<Str1, typename mpl::end<Str1>::type, Str2> {};

int main()
{
  typedef mpl::string<'hell', 'o'> str1;
  typedef mpl::string<' wor', 'ld!'> str2;

  typedef concat<str1,str2>::type str;

  std::cout << mpl::c_str<str>::value << std::endl;

  std::cin.get();
}

使用该结构,您应该能够在纯元编程中实现您的 FizzBu​​zz。顺便说一句,很好的练习。

【讨论】:

  • 谢谢!由于 boost::mpl 是一个纯模板库,所以我可以使用它。
  • 不过,我无法让pastebin.com/CjT0iSRw 工作。如果在 main() 中将 8 替换为 7,就可以了,否则无法编译。似乎是一些 mpl 实现限制,不能执行超过 7 个连接。
  • 您需要在包含标头之前通过设置 BOOST_MPL_LIMIT_STRING_SIZE 来增加 mpl::string 的最大长度(它是 C++03 版本的可变参数模板..预处理器构建)。您将在 BOOST_PP_LIMIT_MAG-3 处遇到总最大值,并且可能在此之前您的编译器最大宏深度。我可以设置为 150,但不能设置为 200。您可能需要更改问题,只需轻轻一点即可。无论如何,100 次迭代并不是问题的关键部分。看起来你无论如何都可以解决它......
【解决方案2】:

您可以解决使您的std::cout &lt;&lt; StringConcat&lt;foo, bar&gt; 工作的问题。

template<CCTYPE...> struct StrBag {};
template<CCTYPE ...Str> void StringConcat(StrBag<Str...>) {}

std::ostream &print(std::ostream &os) { 
  return os; 
}

template<typename ...T> 
std::ostream &print(std::ostream &os, CCTYPE t1, T ...t) { 
  os << t1; 
  return print(os, t...);
}

template<CCTYPE ...Str>
std::ostream &operator<<(std::ostream &os, void(StrBag<Str...>)) {
  return print(os, Str...) << std::endl;
}

现在你可以说

char foo[] = "foo"; char bar[] = "bar";
int main() {
  std::cout << StringConcat<foo, bar> << std::endl;
}

希望对你有帮助。

【讨论】:

  • Schaub:我想知道这是一个完整的解决方案吗?因为我无法编译你的代码。对不起,我的知识有限。
  • @Chan 它旨在成为一个完整的解决方案。见ideone.com/LzO5Y。你不需要为问而感到抱歉:)我只是看到我没有得到保证的评估顺序,所以 ideone 正确地输出“barfoo”:) 让我修复它。
【解决方案3】:

不可能。 foo 和 bar 不是编译时常量。当您可以使用普通的旧函数时,也没有理由这样做:

char foo[] = "foo"; char bar[] = "bar";
std::cout << StringConcat(foo, bar);

【讨论】:

  • 这里描述了我发现将字符串文字传递给模板的唯一方法:comeaucomputing.com/techtalk/templates/#stringliteral
  • (1) 数组 编译时常量(或者更确切地说,它们是可以衰减为指针的外部符号,而指针又可以用作编译时常量) .他们的内容也是如此。否则问题中链接的代码也不起作用。 (2) 原因现在在问题中陈述:好奇心。一个强有力的理由。
  • @Konrad:从分配这些数组的问题来看,这一点并不明显。如果它们是本地人,那么它们不是编译器时间常数。无论哪种方式,它们的内容不是不变的。
【解决方案4】:

可以使用可变数量的字符。但是,我相信没有现有的方法可以连接这样定义的字符串。

【讨论】:

    【解决方案5】:

    你不能连接两个或多个字符串文字,期望得到一个字符串文字(除非你想使用宏)。但是根据手头的任务,您的模板函数可以返回例如 std::string,它是字符串文字的串联。后者是微不足道的。

    【讨论】:

      猜你喜欢
      • 2020-02-17
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-24
      相关资源
      最近更新 更多