C++ template string concatenation
Asked Answered
C

5

11

I'm trying to define some variadic template like that:

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

so that I could write sth like:

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

and it printed foobar. How can I do this, if it's possible in C++0x?

my real interest is to solve FizzBuzz problem using c++ templates, I found a solution here to convert an int to char[] using templates.

Caffeine answered 14/1, 2011 at 17:10 Comment(2)
What's wrong with passing those two strings as regular parameters?Gilles
That's not a problem to concat strings regularly, I would like to do that using templates only, I added a paragraph that describes what I'm doing.Caffeine
T
6
#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();
}

Using that construct you should be able to implement your FizzBuzz in pure metaprogramming. Nice exercise BTW.

Timpani answered 14/1, 2011 at 17:23 Comment(3)
Thanks! As boost::mpl is a pure template library, that's what I can use.Caffeine
Still, I can't make this pastebin.com/CjT0iSRw work. If you replace 8 by 7 in main(), it's ok, otherwise it doesn't compile. Seems to be some mpl implementation limitation, cannot perform more than 7 concatenations.Caffeine
You need to increase the maximum length of an mpl::string by setting BOOST_MPL_LIMIT_STRING_SIZE before including the header (it's C++03 version of variadic templates..preprocessor built). You're going to run into a total maximum at BOOST_PP_LIMIT_MAG-3 and possibly your compilers maximum macro depth before that. I was able to set to 150, but not 200. You might have to change the problem just a touch to make it possible. The 100 iterations isn't the key part of the problem anyway. Looks like you might have solved it at any rate...Timpani
S
5

You can solve the problem of making your std::cout << StringConcat<foo, bar> work.

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

Now you can say

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

Hope it helps.

Siobhan answered 14/1, 2011 at 17:22 Comment(2)
Schaub: I wonder was it a complete solution? cause I could not get your code compiled. Sorry for my limiting knowledge.Gilles
@Chan it was intended to be a complete solution. See ideone.com/LzO5Y . You don't need to be sorry for asking :) I just see I don't get a guaranteed order of evaluation though, so that ideone rightfully outputs "barfoo" :) Lemme fix it.Siobhan
C
1

Impossible. foo and bar are not compile time constants. There is also no reason to do this when you can use plain old functions:

char foo[] = "foo"; char bar[] = "bar";
std::cout << StringConcat(foo, bar);
Chaco answered 14/1, 2011 at 17:14 Comment(3)
The only way I found to pass a string literal to template is described here: comeaucomputing.com/techtalk/templates/#stringliteralCaffeine
(1) the arrays are compile-time constants (or rather, they are external symbols that can decay to pointers which in turn can be used as compile-time constants). As are their contents. Otherwise the code linked to in the question wouldn’t work either. (2) The reason is now stated in the question: curiosity. A powerful reason.Else
@Konrad: it's not apparent from the question where these arrays are allocated. If they are locals then they are not compiler time constant. Their content is not constant either way.Chaco
S
0

It is possible to take variable amounts of characters. However, I believe that there is no existing way to concatenate strings defined like that.

Southland answered 14/1, 2011 at 17:17 Comment(0)
P
0

You cannot concatenate two or more string literals expecting to get a single string literal (unless you want to use macros). But depending on the task at hand you can your template function return, for example, a std::string, which is a concatenation of string literals. The latter is trivial.

Predate answered 14/1, 2011 at 17:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.