2

長さ不明の文字列を Boost のプリプロセッサ ライブラリで展開したい。

たとえば、私はこれが欲しい:

const string foo{"bar"};

私のマクロでこれに展開するには:

foo[0]、foo[1]、foo[2]、'\0'

これが私のコードです。これは主にhereからコピーしたものです。

#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/control/deduce_d.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>

#define EXPAND(first, last) BOOST_PP_REPEAT( BOOST_PP_INC( BOOST_PP_SUB((last), (first)), EXPAND_M, ((first), BOOST_DEDUCE_D())), '\0'

#define EXPAND_M(z, n, data) EXPAND_M_2((n), BOOST_PP_TUPLE_ELEM(2, 0, (data)), BOOST_PP_TUPLE_ELEM(2, 1, (data)))

#define EXPAND_M_2(n, first, d) foo[BOOST_PP_ADD_D((d), (n), (first))],

このまま使ってもいいですか?

const string foo{"bar"};

cout << string{ EXPAND(0, foo.size()) } << endl;
4

2 に答える 2

3

(末尾の) NUL 文字を含める方法を探しているだけですか?

#include <algorithm>
#include <iterator>
#include <iostream>
#include <sstream>

template <typename R = std::string, size_t N>
R stringlit(char const(&lit)[N]) {
    return R(lit+0, lit+N);
}

static std::string const foo(stringlit("bar"));
static auto        const bar(stringlit<std::vector<int>>("bar"));

int main() { 
    std::cout << "foo: ";
    for(char ch : bar)
        std::cout << std::showbase << std::hex << static_cast<int>(ch) << " ";

    std::cout << "\nbar: ";
    for(int i : bar)
        std::cout << std::showbase << std::hex << i << " ";
}

版画

foo: 0x62 0x61 0x72 0 
bar: 0x62 0x61 0x72 0 

おそらく関連するバリエーション:

テンプレート エイリアスを使用して、配列リテラルのサイズを一時的に明示的に指定することもできます。

template <typename T> using Alias = T;

static std::string const foo(stringlit(Alias<char[7]>{"bar"})); // 4 trailing '\0's
于 2014-12-22T14:43:58.190 に答える
3

プリプロセッサはトークンのみで動作するため、渡す文字列の長さをfooハードコードされたマジック定数、つまり整数リテラルとして指定する必要があります。これを回避する方法はありません。
また、この整数リテラルは文字列リテラルから独立しているため、全体のアプローチはエラーが発生しやすく、回避する必要があります。

柔軟な展開が必要な場合は、代わりに可変個引数テンプレートを使用してください。(これが必要なユースケースを提供していないため、何を使用すべきかを判断するのは困難です!)

于 2014-12-22T14:11:15.100 に答える