サイズ制限なしで文字列をコンパイル時に大文字に変換できますか?コンパイル時に文字列を大文字に変換
例:.:
char* myString = TO_UPPERCASE("a big string here!");
を生成する:
char* myString = "A BIG STRING HERE!";
サイズ制限なしで文字列をコンパイル時に大文字に変換できますか?コンパイル時に文字列を大文字に変換
例:.:
char* myString = TO_UPPERCASE("a big string here!");
を生成する:
char* myString = "A BIG STRING HERE!";
これは、Boost.HanaとC++ 14を使用して、可能です。
#include <iostream>
#include <boost/hana/unpack.hpp>
#include <boost/hana/string.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/value.hpp>
#include <boost/hana/core/to.hpp>
constexpr char to_upper(char c) noexcept
{
switch(c) {
default: return c;
case 'b': return 'B';
case 'i': return 'I';
case 'g': return 'G';
case 's': return 'S';
case 't': return 'T';
case 'r': return 'R';
case 'n': return 'N';
// The other characters in the alphabet.
}
}
auto to_upper_str = [](auto hana_str) noexcept {
return boost::hana::unpack(hana_str, [](auto... chars) noexcept {
return boost::hana::string_c<
boost::hana::char_c<to_upper(boost::hana::value(chars))>...>;
});
};
int main()
{
auto str = to_upper_str(BOOST_HANA_STRING("Big string."));
std::cout << boost::hana::to<const char*>(str) << '\n';
}
これはBIG STRING.
はColiruで見る出力します。
[documentation](http://www.boost.org/doc/libs/1_62_0/libs/hana/doc/html/structboost_1_1hana_1_1string.html#a7f15faa77e126e1c2b08a2224ceefb84)によると、「BOOST_HANA_STRING」は使用できません評価されていない文脈では、例えば、テンプレートのパラメータの値を渡します... –
限り、あなたはテンプレートに直接文字列のチェーンを渡すためにしようとはしません、あなたは、さらにあなたは、このコードを利用することができupper_casedされるように、このシーケンスを格納するためのヘルパー変数を作成して(C++ 1Z):
#include <utility>
#include <iostream>
#include <type_traits>
#include <typeinfo>
template <class T>
struct string_literal_length;
template <std::size_t N>
struct string_literal_length<char const[N]>{
static constexpr std::size_t value = N;
};
template <class STR_T, STR_T &, class = std::make_index_sequence<string_literal_length<STR_T>::value>>
struct string_literal;
template <class STR_T, STR_T &STR, std::size_t... Is>
struct string_literal<STR_T, STR, std::index_sequence<Is...>> {
static constexpr std::size_t size = string_literal_length<STR_T>::value;
static constexpr char value[string_literal_length<STR_T>::value] = {STR[Is]...};
};
constexpr char str[] = "abc";
template <class SL, class = std::make_index_sequence<SL::size>>
struct string_literal_to_upper;
template <class SL, std::size_t... Is>
struct string_literal_to_upper<SL, std::index_sequence<Is...>>{
static constexpr char value[SL::size] = { ((SL::value[Is] >= 'a' && SL::value[Is] <= 'z')?(static_cast<char>(SL::value[Is] - 'a' + 'A')):(SL::value[Is]))...};
};
int main() {
std::cout << string_literal_to_upper<string_literal<decltype(str), str>>::value << std::endl;
}
出力:
ABC
編集:
はVSで動作するようにコードを少し変更する必要があります。
#include <utility>
#include <iostream>
#include <type_traits>
#include <typeinfo>
template <class T>
struct string_literal_length;
template <std::size_t N>
struct string_literal_length<char const[N]>{
static constexpr std::size_t value = N;
};
template <class STR_T, STR_T *, class = std::make_index_sequence<string_literal_length<STR_T>::value>>
struct string_literal;
template <class STR_T, STR_T *STR, std::size_t... Is>
struct string_literal<STR_T, STR, std::index_sequence<Is...>> {
static constexpr std::size_t size = string_literal_length<STR_T>::value;
static constexpr char value[string_literal_length<STR_T>::value] = { (*STR)[Is]...};
};
struct Literal {
static constexpr char const str[] = "abc";
};
template <class SL, class = std::make_index_sequence<SL::size>>
struct string_literal_to_upper;
template <class SL, std::size_t... Is>
struct string_literal_to_upper<SL, std::index_sequence<Is...>>{
static constexpr char value[SL::size] = { ((SL::value[Is] >= 'a' && SL::value[Is] <= 'z')?(static_cast<char>(SL::value[Is] - 'a' + 'A')):(SL::value[Is]))...};
};
int main() {
std::cout << string_literal_to_upper<string_literal<decltype(Literal::str), &Literal::str>>::value << std::endl;
}
いいえ、それは不可能です。何のためにそれが必要ですか? –
私はテンプレートのメタプログラミングを研究しています。実際には、私はそれが本当にC + + 17で可能であることを知った。私はそれを行うことができたときに私は答えを投稿する。 – karliwson
型は 'char *'ではなく 'char const [N]'でなければなりません。または少なくとも 'char const *'。あるいは、おそらくC++ 11の文字列リテラルです。 –