基于SFINAE与std::enable_if的C++类型包装类实现练习
完善基于std::enable_if的type_wrap结构体实现
看起来你想用SFINAE机制通过std::enable_if实现一个能包装特定类型的type_wrap结构体,还想通过构造函数重载区分不同类型的处理逻辑对吧?我来帮你把这段代码补全,让它能正确完成类型包装和信息输出的功能。
先给你看完整的可运行代码:
#include <type_traits> #include <typeinfo> #include <iostream> #include <string> using std::enable_if; using std::is_same; using std::cout; using std::endl; using std::string; template<typename T> struct type_wrap { // 存储被包装的实例 T value; // 专门处理int类型的构造函数,通过SFINAE启用 type_wrap(typename enable_if<is_same<int, T>::value, T>::type&& rrT) : value(std::move(rrT)) { cout << "The wrapped type is int, value: " << value << endl; } // 扩展:专门处理float类型的构造函数 type_wrap(typename enable_if<is_same<float, T>::value, T>::type&& rrT) : value(std::move(rrT)) { cout << "The wrapped type is float, value: " << value << endl; } // 扩展:专门处理std::string类型的构造函数 type_wrap(typename enable_if<is_same<string, T>::value, T>::type&& rrT) : value(std::move(rrT)) { cout << "The wrapped type is std::string, value: " << value << endl; } // 通用构造函数,处理未专门重载的其他类型 template<typename U = T, typename = typename enable_if< !is_same<U, int>::value && !is_same<U, float>::value && !is_same<U, string>::value >::type> type_wrap(U&& val) : value(std::forward<U>(val)) { cout << "The wrapped type is " << typeid(T).name() << ", value: " << value << endl; } }; int main() { // 测试不同类型的包装 type_wrap<int> int_wrap(42); type_wrap<float> float_wrap(3.14f); type_wrap<string> str_wrap("Hello World"); type_wrap<double> double_wrap(2.718); // 触发通用构造函数 return 0; }
接下来拆解几个关键部分,帮你理解为什么要这么写:
- 核心成员变量:给
type_wrap添加了T value;,这是用来存储被包装的类型实例的基础,没有它包装结构体就失去了意义。 - SFINAE构造函数重载:每个针对特定类型的构造函数都用
enable_if<is_same<目标类型, T>::value, T>::type限定参数类型。简单说,只有当模板参数T和我们指定的类型(比如int)完全匹配时,这个构造函数才会被编译器识别,否则会被自动忽略——这就是SFINAE(Substitution Failure Is Not An Error)的核心作用,实现编译期的函数重载筛选。 - 类型信息输出:对于明确指定的类型(比如int、float),直接输出清晰的类型名称;对于其他未专门处理的类型,用
typeid(T).name()获取编译器提供的类型标识(注意这个标识格式是编译器相关的,比如GCC里int会显示i,MSVC里会显示int)。 - 通用构造函数:用额外的模板参数和
enable_if排除已经有专门重载的类型,确保所有其他类型都能正常构造,同时输出对应的类型和值信息。这里用std::forward实现完美转发,保证参数传递的效率。 - 移动语义:构造函数使用右值引用(
&&)并配合std::move传递参数,避免不必要的拷贝操作,提升代码效率。
运行这段代码后,你会看到类似这样的输出(不同编译器可能略有差异):
The wrapped type is int, value: 42 The wrapped type is float, value: 3.14 The wrapped type is std::string, value: Hello World The wrapped type is d, value: 2.718
内容的提问来源于stack exchange,提问作者user9196120
相关产品推荐
相关产品推荐

