在编译时将字符串转换为大写

时间:2016-12-03 08:19:48

标签: c++ macros metaprogramming

是否可以在编译时将字符串转换为大写而没有任何大小限制?

例如:

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

会生成:

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

2 个答案:

答案 0 :(得分: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 :(得分:0)

只要您不想尝试将字符串链直接传递给模板,并创建辅助变量来存储此序列,以便进一步使用此代码(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]