Question

I have a vector of mpl::string. mpl::string size limit is 32 elements. Have a way to create const char* array in compile time

 MACRO(z,i,data) data
 .............
 const char* array[] = { BOOST_PP_ENUM(SIZE,MACRO,mpl_vector) };

But i need get a one const char* string in compile time. How to make it?

UPDATE I create an array of mpl::string in compile time. They compressed (size of every string about 25-31 with limit of 32). I may get array from it strings like

  //first,second string etc is mpl::c_str<mpl_string>::value
  const char* array_mpl_strings[] = {first_string,second_string .....};

But i need a complete string (not array):

  const char* string = first_stringsecond_string....;

How do "string" from "array_mpl_strings"?

Was it helpful?

Solution

I don't know the reason about BOOST_MPL_STRING_MAX_LENGTH

but following may help if you could convert your type:

#include <cassert>
#include <cstring>
#include <tuple>


template<char...Cs> struct seq
{
    typedef const char (&arr_type)[sizeof...(Cs) + 1];
    static constexpr arr_type c_str() { return str; }
    static constexpr char str[sizeof...(Cs) + 1] = {Cs..., '\0'};
};

template<char...Cs>
constexpr char seq<Cs...>::str[sizeof...(Cs) + 1];


template<typename T, typename ... Ts>
struct concat_seq;

template<char...Cs>
struct concat_seq<seq<Cs...>> : seq<Cs...> {};

template<char...Cs1, char...Cs2>
struct concat_seq<seq<Cs1...>, seq<Cs2...>> : seq<Cs1..., Cs2...> {};

template<char...Cs1, char...Cs2, typename ... Ts>
struct concat_seq<seq<Cs1...>, seq<Cs2...>, Ts...> :
    concat_seq<seq<Cs1..., Cs2...>, Ts...> {};

template<typename ... Ts>
struct concat_seq<std::tuple<Ts...>> : concat_seq<Ts...> {};

int main()
{
    const char* s = concat_seq<std::tuple<seq<'h', 'e'>, seq<'l', 'l', 'o'>>>::c_str();

    assert(strcmp(s, "hello") == 0);

    return 0;
}

OTHER TIPS

For their, who interested final variant:

#include <boost/preprocessor.hpp>
#include <boost/static_assert.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/if.hpp>

#include <iostream>
#include <cstring>
#include <exception>
#include <stdexcept>


#define NUM_CHARS 32
#define CHARS_GEN(count,i,data) data ## i
#define GEN_CHARSP(N) BOOST_PP_ENUM(N,CHARS_GEN,char C)
#define GEN_CHARS(N) BOOST_PP_ENUM(N,CHARS_GEN, C)

/*Jarod42 classes*/
template<char...Cs> struct seq
{
    typedef const char (&arr_type)[sizeof...(Cs) + 1];
    static constexpr arr_type c_str() { return str; }
    static constexpr char str[sizeof...(Cs) + 1] = {Cs..., '\0'};
};

template<char...Cs>
constexpr char seq<Cs...>::str[sizeof...(Cs) + 1];


template<typename T, typename ... Ts>
struct concat_seq;

template<char...Cs>
struct concat_seq<seq<Cs...>> : seq<Cs...> {
    typedef seq<Cs...> type;
};

template<char...Cs1, char...Cs2>
struct concat_seq<seq<Cs1...>, seq<Cs2...>> : seq<Cs1..., Cs2...> {
    typedef seq<Cs1...,Cs2...> type;
};

template<char...Cs1, char...Cs2, typename ... Ts>
struct concat_seq<seq<Cs1...>, seq<Cs2...>, Ts...> :
    concat_seq<seq<Cs1..., Cs2...>, Ts...> {};

template<typename ... Ts>
struct concat_seq<std::tuple<Ts...>> : concat_seq<Ts...> {};

/*Abrahams function*/
template <int N>
constexpr char at(char const(&s)[N], int i)
{
  return i >= N ? '\0' : s[i];
}

#define AT(count,i,s) at(s,i)

namespace mpl = boost::mpl;

/*My modification, but abraham's way */
template<size_t N>
constexpr size_t str_size(const char (&a)[N]){
    return N-1;
}
#define PRE_MACRO(z,i,s) \
     typename                                                           \
        mpl::if_<                                                       \
        typename mpl::equal_to<mpl::int_<i>,mpl::int_<N> >::type,       \
                 seq<GEN_CHARS(i)>,
#define POST_MACRO(z,i,s) >::type

/*TODO: incorect count of paramenters N is 31, params is 32*/
template <size_t N, GEN_CHARSP(NUM_CHARS)> 
struct create_sequence  {   
    typedef 
    BOOST_PP_REPEAT(NUM_CHARS,PRE_MACRO,"")
    void
    BOOST_PP_REPEAT(NUM_CHARS,POST_MACRO,"")
    type;
};

#define _S(s) create_sequence<str_size(s),BOOST_PP_ENUM(NUM_CHARS,AT,s)>::type

int main()
{
      typedef _S("first_string_sequence ") sq1;
      typedef _S("second_string_sequence ") sq2;
      typedef _S("И такие строки ") sq3;   

      std::cout << sq1::c_str() << std::endl;
      std::cout << sq2::c_str() << std::endl;
      std::cout << sq3::c_str() << std::endl;

      typedef concat_seq<std::tuple< sq1, sq2 >>::type str1;
      typedef concat_seq<std::tuple< str1, sq3 >>::type str2;


      std::cout << str1::c_str() << std::endl;
      std::cout << str2::c_str() << std::endl;


    return 0;
}

It more than needed. It initialize from UTF-8 strings without problem.

http://coliru.stacked-crooked.com/a/9039c901822fcabc

I found more compact way of achieving concatenating const chars in compile time using boost. Here is ready to go header file StaticString.h:

#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <boost/preprocessor.hpp>
#include <boost/mpl/string.hpp>
#include <boost/mpl/copy_if.hpp>

template <typename S1, typename S2>
struct Concatenate {
    typedef typename boost::mpl::copy_if<
            S2,
            boost::mpl::not_<
                boost::is_same<
                    boost::mpl::_1,
                    boost::mpl::integral_c<char, '\0'>>
            >,
            boost::mpl::back_inserter< S1 >
    >::type type;
};

// sink template parameter _ simplifies AT macro
template<typename _, char ... CHARS>
struct StaticString {
private:
    typedef typename boost::mpl::vector_c<char, CHARS...>::type _input;
public:
    // this is needed to remove '\0' from the end of _input
    typedef typename Concatenate<
            boost::mpl::vector_c<char>,
            _input
    >::type type;
};

#define AT(z, i, data) , i < sizeof(data) ? data[i] : '\0'
#define _S(s) StaticString<char BOOST_PP_REPEAT(16, AT, s) >::type

And example of it's use:

#include "StaticString.h"

#include <iostream>
using namespace std;
using boost::mpl::c_str;
using boost::mpl::size;

int main()
{
    typedef _S("Hello ") Hello;
    cout << c_str<Hello>::value << endl;
    cout << size<Hello>::type::value << endl;

    typedef _S("World!") World;
    cout << c_str<World>::value << endl;
    cout << size<World>::type::value << endl;

    typedef Concatenate<Hello, World>::type concatenated;
    cout << c_str<concatenated>::value << endl;
    cout << size<concatenated>::type::value << endl;

    return 0;
}

Output should be:

Hello 
6
World!
6
Hello World!
12
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top