C++20中能否通过宏传参实现constexpr函数返回含静态数组的类型元组?
问题:将宏参数的无引号字符串字面量转为constexpr环境可访问的唯一类型字符串
需要将宏参数传入的无引号字符串字面量,转换为可在constexpr环境中访问的字符串(支持前缀拼接),优先实现为带static constexpr array<char, N>的唯一类型(例如模板A<1>,其中A<1>::str为对应字符串的静态constexpr数组),也可接受模板参数形式(如template<... 'h','e'...>)。
测试用例
头文件部分
#include <array> #include <tuple> #include <cassert> #include <string> #include <iostream>
待修正的演示代码
template<int I> struct A; template<> struct A<0> { static constexpr auto str = std::to_array("abc"); // 此处硬编码的"abc"应来自宏参数 }; template<> struct A<1> { static constexpr auto str = std::to_array("def"); // 同上 }; constexpr auto f(char const* s0, char const* s1) { return std::tuple< A<0>, // 0使类型唯一,其静态数组应包含s0对应字符串 A<1> // 同理 >{}; } #define STR(arg) #arg #define STRINGIFY(arg) STR(arg) #define MEMBER(arg) STRINGIFY(arg)
不可修改的测试代码
//===================================================================== // NOTHING BELOW THIS LINE MAY BE CHANGED. struct C { static constexpr auto x = f( MEMBER(abc), MEMBER(def) ); }; int main() { // The type returned by f() is a tuple. using xt = decltype(C::x); // Each element of that tuple must be a type... using e0 = std::tuple_element_t<0, xt>; using e1 = std::tuple_element_t<1, xt>; // ... that defines a static constexpr array<> 'str'. constexpr std::array a0 = e0::str; constexpr std::array a1 = e1::str; std::string s0{a0.begin(), a0.end()}; // Note that the array str includes a terminating zero. std::string s1{a1.begin(), a1.end()}; std::cout << "s0 = \"" << s0 << "\"\n"; std::cout << "s1 = \"" << s1 << "\"\n"; // ... that has the value that was passed as macro argument. assert(s0.compare("abc") && s0[3] == '\0'); assert(s1.compare("def") && s1[3] == '\0'); }
当前代码的问题
- 字符串为硬编码,未从宏参数获取
f()的参数未被实际使用- 未满足核心需求:每个
f()参数需对应返回元组中的一个唯一类型元素,该类型需包含对应宏参数的静态constexpr数组
可行解决方案代码
template<std::size_t N> struct TemplateStringLiteral { std::array<char, N> chars; consteval TemplateStringLiteral(std::array<char, N> literal) : chars(literal) { } }; template<TemplateStringLiteral literal> struct B { static constexpr auto str = literal.chars; }; template<TemplateStringLiteral s> struct Wrap { }; template <TemplateStringLiteral s0, TemplateStringLiteral s1> consteval auto f(Wrap<s0>, Wrap<s1>) { return std::tuple< B<s0>, B<s1> >{}; } #define STR(arg) #arg #define STRINGIFY(arg) STR(arg) #define MEMBER(arg) Wrap<std::to_array(STRINGIFY(arg))>{}
内容的提问来源于stack exchange,提问作者Carlo Wood
相关产品推荐
相关产品推荐

