2016-12-03 13 views
2

サイズ制限なしで文字列をコンパイル時に大文字に変換できますか?コンパイル時に文字列を大文字に変換

例:.:

char* myString = TO_UPPERCASE("a big string here!"); 

を生成する:

char* myString = "A BIG STRING HERE!"; 
+5

いいえ、それは不可能です。何のためにそれが必要ですか? –

+2

私はテンプレートのメタプログラミングを研究しています。実際には、私はそれが本当にC + + 17で可能であることを知った。私はそれを行うことができたときに私は答えを投稿する。 – karliwson

+1

型は 'char *'ではなく 'char const [N]'でなければなりません。または少なくとも 'char const *'。あるいは、おそらくC++ 11の文字列リテラルです。 –

答えて

1

これは、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で見る出力します。

+1

[documentation](http://www.boost.org/doc/libs/1_62_0/libs/hana/doc/html/structboost_1_1hana_1_1string.html#a7f15faa77e126e1c2b08a2224ceefb84)によると、「BOOST_HANA_STRING」は使用できません評価されていない文脈では、例えば、テンプレートのパラメータの値を渡します... –

0

限り、あなたはテンプレートに直接文字列のチェーンを渡すためにしようとはしません、あなたは、さらにあなたは、このコードを利用することができ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

[live demo]

編集:

は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; 
} 

[live demo]

+0

ヘルパー変数を宣言し、テンプレートを使用して変数の ':: value'を返すconstexpr関数を持つことは可能ですか?そうすれば、簡単な 'TO_UPPERCASE()'マクロを書くことができます。私はそれを試みましたが、私はまだパラメータロジックに慣れていません。 – karliwson

+0

また、Visual Studio 2015のアップデート3では、エラーC2754 'エラーC2754' string_literal > ':部分的な特殊化に依存しない型テンプレートパラメータ ' – karliwson

関連する問題