views:

137

answers:

4

In C# and Java, it's possible to create constant strings using one or more other constant strings. I'm trying to achieve the same result in C++ (actually, in C++0x, to be specific), but have no idea what syntax I would use to achieve it, if such a thing is possible in C++. Here's an example illustrating what I want to do:

#include <stdio.h>

const char array1[] = "Hello ";
const char array2[] = "world!\n";
const char array3[] = array1 + array2; // C++ doesn't like it when I try this

int main() {

    printf(array3);

    return 0;

}

Any pointers? (No pun intended.)

EDIT: I need to be able to apply this to integer arrays as well - not just char arrays. However, in both cases, the to-be-combined arrays will be fixed-size and be compile-time constants.

+3  A: 

In cases like this preprocessor often comes handy

#define ARRAY1 "Hello "
#define ARRAY2 "world!\n"

const char array1[] = ARRAY1;
const char array2[] = ARRAY2;
const char array3[] = ARRAY1 ARRAY2;

Note: no + necessary.

AndreyT
The preprocessor is a beautiful thing, but I specifically need to work with const's. I'm using variadic templates, and while the arrays' sizes and contents will be known at compile-time, I don't know any way of creating macros for them.
nonoitall
If you want a compile time concatenation this is the right way to go
bjg
@nonoitall: You *are* working with consts in this case. Preprocessor is only used to *initialize* these consts uniformly. Isn't that obvious from the above code sample?
AndreyT
The preprocessor needs something to work with though - something I can't give it. I'm creating a template class with a variable number of arguments, and the template has a static array with the same number of elements as the template has parameters. These elements are to be initialized to the offset in the class where each of the template's custom members are located. I know of no way to pass this information to the preprocessor, though all of it is known at compile-time.
nonoitall
+2  A: 

Use a string object:

#include <iostream>
#include <string>

const std::string s1 = "Hello ";
const std::string s2 = "world!\n";
const std::string s3 = s1 + s2;

int main()
{
  std::cout << s3 << std::endl;
}
SCFrench
You'll want to make those const to be equivalent to the OP.
Noah Roberts
Yeah, I realized that about 5 seconds after the original post. Fixed now.
SCFrench
I'm also going to need to work with integer arrays. I'd use concatenation at runtime (which std::string does) as a last resort, but would prefer to have compile-time constants if at all possible.
nonoitall
+2  A: 

In C++0x you can do the following:

template<class Container>
Container add(Container const & v1, Container const & v2){
   Container retval;
   std::copy(v1.begin(),v1.end(),std::back_inserter(retval));
   std::copy(v2.begin(),v2.end(),std::back_inserter(retval));
   return retval;
}

const std::vector<int> v1 = {1,2,3};
const std::vector<int> v2 = {4,5,6};
const std::vector<int> v3 = add(v1,v2);

I don't think there's any way to do this for STL containers in C++98 (the addition part for v3 you can do, but you can't use the initializer lists for v1 and v2 in C++98), and I don't think there's any way to do this for raw arrays in C++0x or C++98.

Ken Bloom
Thanks. I'm still holding out for a compile-time solution if one presents itself, but will probably use vectors or dynamic arrays if none does.
nonoitall
In C++1x, this should use `constexpr` instead of `const`.
sbi
@sbi this will not work just by adding constexpr, the keyword is not applied to function arguments besides. constexpr functions can only have one return expression statement that has to be a constant expression itself. The only mechanism to loop in a constexpr is via recursion.
snk_kid
@snk_kid: Sounds like you're right. (I wish I had time to play with a C++11 compiler.)
sbi
+5  A: 

So...

You don't want to do runtime concatination.

You don't want to use the preprocessor.

You want to work with constants and output constants.

OK. But you're not going to like it:

#include <boost/mpl/string.hpp>

#include <iostream>

int main()
{
  using namespace boost::mpl;

  typedef string<'Hell', 'o '> hello;
  typedef string<'Worl', 'd!'> world;
  typedef insert_range<hello, end<hello>::type, world>::type hello_world;

  std::cout << c_str<hello_world>::value << std::endl;

  std::cin.get();
}
Noah Roberts
The integer version is similar but uses vector_c<>
Noah Roberts