2014-02-25 76 views
4

我有結構的靜態數組:對齊靜態字符串文字

struct CommandStruct 
{ 
    char* data; 
    unsigned ans_size; 
}; 

static const CommandStruct commands[] = 
{ 
    { "Some literal", 28 }, 
    { "Some other literal", 29 }, 
    { "Yet another literal", 8 }, 
}; 

而且我想琴絃爲16字節對齊。是否有可能直接實現它? 我可能會分開定義每個字面值,例如__declspec(align(16)) static const char some_command_id[] = "my literal",但這是一團糟。我需要在一個代碼塊中進行全部初始化。

+0

你想要的指向字符序列的指針('char * data')還是實際的字符? – Liosan

+0

當然是字符。第一個字符必須在16字節的邊界。 –

+0

用戶定義的文字?對齊支持在C++ 11中是新的,需要一些細節,因此您可能需要自己的「對齊字符串」類。 –

回答

2

用C++ 11 ,以下可能會有所幫助:https://ideone.com/IDEdY0

#include <cstdint> 

// Sequence of char 
template <char...Cs> struct char_sequence 
{ 
    template <char C> using push_back = char_sequence<Cs..., C>; 
}; 

// Remove all chars from char_sequence from '\0' 
template <typename, char...> struct strip_sequence; 

template <char...Cs> 
struct strip_sequence<char_sequence<>, Cs...> 
{ 
    using type = char_sequence<Cs...>; 
}; 

template <char...Cs, char...Cs2> 
struct strip_sequence<char_sequence<'\0', Cs...>, Cs2...> 
{ 
    using type = char_sequence<Cs2...>; 
}; 

template <char...Cs, char C, char...Cs2> 
struct strip_sequence<char_sequence<C, Cs...>, Cs2...> 
{ 
    using type = typename strip_sequence<char_sequence<Cs...>, Cs2..., C>::type; 
}; 

// struct to create a aligned char array 
template <std::size_t Alignment, typename chars> struct aligned_string; 

template <std::size_t Alignment, char...Cs> 
struct aligned_string<Alignment, char_sequence<Cs...>> 
{ 
    alignas(Alignment) static constexpr char str[sizeof...(Cs)] = {Cs...}; 
}; 

template <std::size_t Alignment, char...Cs> 
alignas(Alignment) constexpr 
char aligned_string<Alignment, char_sequence<Cs...>>::str[sizeof...(Cs)]; 

// helper to get the i_th character (`\0` for out of bound) 
template <std::size_t I, std::size_t N> 
constexpr char at(const char (&a)[N]) { return I < N ? a[I] : '\0'; } 

// helper to check if the c-string will not be truncated 
template <std::size_t max_size, std::size_t N> 
constexpr bool check_size(const char (&)[N]) 
{ 
    static_assert(N <= max_size, "string too long"); 
    return N <= max_size; 
} 

// Helper macros to build char_sequence from c-string 
#define PUSH_BACK_8(S, I) \ 
    ::push_back<at<(I) + 0>(S)>::push_back<at<(I) + 1>(S)> \ 
    ::push_back<at<(I) + 2>(S)>::push_back<at<(I) + 3>(S)> \ 
    ::push_back<at<(I) + 4>(S)>::push_back<at<(I) + 5>(S)> \ 
    ::push_back<at<(I) + 6>(S)>::push_back<at<(I) + 7>(S)> 

#define PUSH_BACK_32(S, I) \ 
     PUSH_BACK_8(S, (I) + 0) PUSH_BACK_8(S, (I) + 8) \ 
     PUSH_BACK_8(S, (I) + 16) PUSH_BACK_8(S, (I) + 24) 

#define PUSH_BACK_128(S, I) \ 
    PUSH_BACK_32(S, (I) + 0) PUSH_BACK_32(S, (I) + 32) \ 
    PUSH_BACK_32(S, (I) + 64) PUSH_BACK_32(S, (I) + 96) 

// Macro to create char_sequence from c-string (limited to 128 chars) 
#define MAKE_CHAR_SEQUENCE(S) \ 
    strip_sequence<char_sequence<> \ 
    PUSH_BACK_128(S, 0) \ 
    >::type::template push_back<check_size<128>(S) ? '\0' : '\0'> 

// Macro to return an aligned c-string 
#define MAKE_ALIGNED_STRING(ALIGNMENT, S) \ 
    aligned_string<ALIGNMENT, MAKE_CHAR_SEQUENCE(S)>::str 

等你:

static const CommandStruct commands[] = 
{ 
    { MAKE_ALIGNED_STRING(16, "Some literal"), 28 }, 
    { MAKE_ALIGNED_STRING(16, "Some other literal"), 29 }, 
    { MAKE_ALIGNED_STRING(16, "Yet another literal"), 8 }, 
}; 
+0

它在爲你工作嗎?它返回:'警告:數組索引125超過了數組的末尾(包含6個元素)[-Warray-bounds]'對我來說 – RushPL

+0

@RushPL:地址的'static_assert'不被支持, http://coliru.stacked-crooked.com/a/5dc1419e638a9776)。 – Jarod42

+0

事實證明,它是由不同的錯誤觸發的,並且是誤報。感謝您的及時評論。 – RushPL

0

已經通過提升一點,我已經成功地編造一些東西,只是獨立的自動化建設的文字瀏覽,(我也讓所有的數組元素的枚舉):

#define CMD_TUPLE (\ 
    (cmdCommandOne, "The first command", 1900),\ 
    (cmdCommandTwo, "The second one", 1),\ 
    (cmdAnother, "Another command", 11)) 

#define CMD_SEQ BOOST_PP_TUPLE_TO_SEQ(CMD_TUPLE) 

#define CMD_MAKE_ENUM(r, data, elem) BOOST_PP_TUPLE_ELEM(0, elem), 
enum Commands { BOOST_PP_SEQ_FOR_EACH(CMD_MAKE_ENUM, , CMD_SEQ) cmdLast }; 

#define CMD_MAKE_STRING(r, data, elem) \ 
    __declspec(align(16)) static const char \ 
    BOOST_PP_CAT(cmd_, BOOST_PP_TUPLE_ELEM(0, elem))[] = BOOST_PP_TUPLE_ELEM(1, elem); 
BOOST_PP_SEQ_FOR_EACH(CMD_MAKE_STRING, , CMD_SEQ) 

#define CMD_MAKE_ARRAY(r, data, elem) \ 
    { BOOST_PP_CAT(cmd_, BOOST_PP_TUPLE_ELEM(0, elem)), \ 
    BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_REST_N(2, BOOST_PP_TUPLE_TO_SEQ(elem))) }, 
static const CommandStruct commands[] = { 
    BOOST_PP_SEQ_FOR_EACH(CMD_MAKE_ARRAY, , CMD_SEQ) 
};