我有一个mpl :: string的向量。 mpl :: string size limit是32个元素。有一种方法可以在编译时创建const char *数组
MACRO(z,i,data) data
.............
const char* array[] = { BOOST_PP_ENUM(SIZE,MACRO,mpl_vector) };
但是我需要在编译时获得一个const char *字符串。怎么做?
更新 我在编译时创建了一个mpl :: string数组。他们压缩(每个字符串的大小约25-31,限制为32)。我可以从它的字符串中获取数组
//first,second string etc is mpl::c_str<mpl_string>::value
const char* array_mpl_strings[] = {first_string,second_string .....};
但我需要一个完整的字符串(不是数组):
const char* string = first_stringsecond_string....;
“array_mpl_strings”中的“string”如何?
答案 0 :(得分:1)
我不知道BOOST_MPL_STRING_MAX_LENGTH
但如果您可以转换类型,以下内容可能有所帮助:
#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;
}
答案 1 :(得分:1)
对于他们感兴趣的最终变体:
#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;
}
它超过了需要。它从UTF-8字符串初始化没有问题。
答案 2 :(得分:0)
我发现使用boost在编译时实现连续const字符的更简洁方法。这里准备好去头文件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
以及它的使用示例:
#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;
}
输出应为:
Hello
6
World!
6
Hello World!
12