C++17中如何从<TYPE,INT>参数包提取TYPE并传给std::variant作为基类?
在C++17中实现Foo继承std::variant并提取参数包中的类型
完全可以实现。核心思路是利用C++17的参数包展开特性,将每个P的type成员提取出来,作为std::variant的模板参数。
修改后的完整代码如下:
#include <variant> #include <iostream> #include <type_traits> template <typename T, int I> struct Type { using type = T; static constexpr int value = I; }; template <typename ...P> struct Foo : std::variant<typename P::type...> { // 继承std::variant的所有构造函数 using std::variant<typename P::type...>::variant; int index = 0; template <typename T, std::enable_if_t<(std::is_same_v<T, typename P::type> || ...), std::nullptr_t> = nullptr> Foo& operator=(const T& val) { // 先调用std::variant的赋值,更新内部值 static_cast<std::variant<typename P::type...>&>(*this) = val; // 匹配对应的类型并设置index (void)((std::is_same_v<T, typename P::type> ? (index = P::value, true) : false) || ...); return *this; } }; int main() { Foo<Type<int, 10>, Type<float, 20>> x; x = 42; std::cout << x.index << '\n'; // 输出10 std::cout << std::get<int>(x) << '\n'; // 输出42 x = 42.f; std::cout << x.index << '\n'; // 输出20 std::cout << std::get<float>(x) << '\n'; // 输出42 // x = 42L; // 编译错误,符合预期 }
关键说明
- 参数包展开:
std::variant<typename P::type...>会将模板参数包P中的每个元素,提取其type成员,最终展开成std::variant<int, float>(对应示例中的参数)。 - 构造函数继承:通过
using std::variant<...>::variant;继承std::variant的所有构造函数,确保Foo可以像普通std::variant一样初始化(比如直接用int或float值构造)。 - 赋值操作增强:在自定义的
operator=中,先调用基类std::variant的赋值操作更新内部存储的值,再匹配类型设置index,保证两者状态一致。
内容的提问来源于stack exchange,提问作者Wad
相关产品推荐
相关产品推荐

