为何模板定义的别名类型匹配void?封装variant的get函数返回void问题
问题分析与解决方案
这个问题的核心在于你对std::enable_if_t的模板参数理解有偏差,咱们一步步拆解来看:
原代码的问题根源
你定义的TType别名:
template<typename T> using TType = enable_if_t< is_same<T, Type::String>::value || is_same<T, Type::Int>::value >;
std::enable_if_t的完整模板签名是std::enable_if_t<bool B, typename T = void>——当第二个模板参数不指定时,默认类型是void。这就意味着,即便你的条件(T是Type::String或Type::Int)满足,TType<T>最终展开的类型也是void,而不是你期望的T。
这直接导致getValue函数的返回类型被推导为void,但你在函数体内返回的是std::get<T>(value)(类型为T),类型完全不匹配,自然会出现编译错误,或者你观察到的“返回了void”的异常情况。
修正方案
方案一:指定enable_if_t的目标类型
修改TType的定义,明确把第三个模板参数设为T,这样当条件满足时,TType<T>就会是你想要的返回类型:
#include <iostream> #include <type_traits> #include <utility> #include <string> #include <variant> using namespace std; struct Type { using String = std::string; using Int = int; }; // 修改此处,添加第三个模板参数T template<typename T> using TType = enable_if_t< is_same<T, Type::String>::value || is_same<T, Type::Int>::value, T >; template<typename T> TType<T> getValue(variant<Type::String, Type::Int> const& value) { return get<T>(value); } int main() { variant<Type::String, Type::Int> value = "Hello"; cout << getValue<Type::String>(value) << endl; // 现在可以正常输出字符串 }
方案二:将enable_if放在模板参数列表中
另一种更清晰的写法是把enable_if放在模板参数里,避免返回类型的歧义:
#include <iostream> #include <type_traits> #include <utility> #include <string> #include <variant> using namespace std; struct Type { using String = std::string; using Int = int; }; // 将enable_if作为模板默认参数 template<typename T, typename = enable_if_t< is_same<T, Type::String>::value || is_same<T, Type::Int>::value >> T getValue(variant<Type::String, Type::Int> const& value) { return get<T>(value); } int main() { variant<Type::String, Type::Int> value = 42; cout << getValue<Type::Int>(value) << endl; // 正常输出整数 }
这两种方案都能解决你的类型匹配问题,让getValue函数正确返回对应类型的值。
内容的提问来源于stack exchange,提问作者kiechant
相关产品推荐
相关产品推荐

