接受 std::array 的任意大小的 char 作为非类型模板参数
Accepting std::array of char of any size as non type template parameter
这可能是一个奇怪的用例,但我试图绕过以下事实:字符串文字不能用作使用 std::array<char, N>
作为非模板类型参数的模板的参数。
这可行,但有一个极端的限制,即所有字符串必须具有相同的长度(我可以使用 MAX_STR_LEN=100
或其他任何东西并使所有数组都具有该大小,但感觉很难看...)。
有没有办法让 this code 可以接受不同大小的 std::array
作为模板参数?
#include <iostream>
#include <array>
#include <tuple>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/tuple.hpp>
// I wish that this 6 is not fixed... but IDK how to fix it, maybe concept(IDK if concepts can be used as "types" on NTTP.
template <typename Type, std::array<char, 6> val_val>
struct TypeToValues
{
using type = Type;
static constexpr const char* val = val_val.data();
};
template <std::size_t Sz, std::size_t... Is>
constexpr std::array<char, Sz>
arrayify(const char (&arr)[Sz], std::index_sequence<Is...>)
{
return {{arr[Is]...}};
}
template <std::size_t Sz>
constexpr std::array<char, Sz> arrayify(const char (&arr)[Sz])
{
return arrayify(arr, std::make_index_sequence<Sz>());
}
struct HelloType{
};
struct YoloType{
};
int main(){
std::tuple<
TypeToValues<HelloType, arrayify("Hello")>,
TypeToValues<YoloType, arrayify("Yolo!")>> mapping;
boost::mp11::tuple_for_each(mapping, []<typename T>(const T&){
if constexpr(std::is_same_v<typename T::type, HelloType>){
std::cout << "HelloType says: " << T::val << std::endl;;
}
if constexpr(std::is_same_v<typename T::type, YoloType>){
std::cout << "YoloType says: " << T::val << std::endl;;
}
});
}
当然,为什么不使用 requires requires 子句?
template <typename Type, auto val_val>
requires requires { { val_val.data() } -> std::same_as<char const*>; }
struct TypeToValues
{
// ...
您还可以编写一个约束条件,专门 std::array<char, N>
满足:
template<class> constexpr bool is_array_of_char_v = false;
template<unsigned N> constexpr bool is_array_of_char_v<std::array<char, N>> = true;
template<class T> concept ArrayOfChar = requires { is_array_of_char_v<T>; };
template <typename Type, ArrayOfChar auto val_val>
struct TypeToValues
{
// ...
但是that感觉限制太多;您将来会希望接受静态字符串类型。
这可能是一个奇怪的用例,但我试图绕过以下事实:字符串文字不能用作使用 std::array<char, N>
作为非模板类型参数的模板的参数。
这可行,但有一个极端的限制,即所有字符串必须具有相同的长度(我可以使用 MAX_STR_LEN=100
或其他任何东西并使所有数组都具有该大小,但感觉很难看...)。
有没有办法让 this code 可以接受不同大小的 std::array
作为模板参数?
#include <iostream>
#include <array>
#include <tuple>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/tuple.hpp>
// I wish that this 6 is not fixed... but IDK how to fix it, maybe concept(IDK if concepts can be used as "types" on NTTP.
template <typename Type, std::array<char, 6> val_val>
struct TypeToValues
{
using type = Type;
static constexpr const char* val = val_val.data();
};
template <std::size_t Sz, std::size_t... Is>
constexpr std::array<char, Sz>
arrayify(const char (&arr)[Sz], std::index_sequence<Is...>)
{
return {{arr[Is]...}};
}
template <std::size_t Sz>
constexpr std::array<char, Sz> arrayify(const char (&arr)[Sz])
{
return arrayify(arr, std::make_index_sequence<Sz>());
}
struct HelloType{
};
struct YoloType{
};
int main(){
std::tuple<
TypeToValues<HelloType, arrayify("Hello")>,
TypeToValues<YoloType, arrayify("Yolo!")>> mapping;
boost::mp11::tuple_for_each(mapping, []<typename T>(const T&){
if constexpr(std::is_same_v<typename T::type, HelloType>){
std::cout << "HelloType says: " << T::val << std::endl;;
}
if constexpr(std::is_same_v<typename T::type, YoloType>){
std::cout << "YoloType says: " << T::val << std::endl;;
}
});
}
当然,为什么不使用 requires requires 子句?
template <typename Type, auto val_val>
requires requires { { val_val.data() } -> std::same_as<char const*>; }
struct TypeToValues
{
// ...
您还可以编写一个约束条件,专门 std::array<char, N>
满足:
template<class> constexpr bool is_array_of_char_v = false;
template<unsigned N> constexpr bool is_array_of_char_v<std::array<char, N>> = true;
template<class T> concept ArrayOfChar = requires { is_array_of_char_v<T>; };
template <typename Type, ArrayOfChar auto val_val>
struct TypeToValues
{
// ...
但是that感觉限制太多;您将来会希望接受静态字符串类型。