C++SFINAE与enable_if应用
C++SFINAE与enable_if应用
SFINAE(替换失败不是错误)是C++模板元编程的核心技术,允许在模板实例化失败时选择其他重载。enable_if根据条件启用或禁用模板。
SFINAE原则:模板替换失败不会导致编译错误。
#include
#include
#include
template
typename std::enable_if::value, void>::type
process(T value) {
std::cout << "Integer: " << value * 2 << "\n";
}
template
typename std::enable_if::value, void>::type
process(T value) {
std::cout << "Float: " << value * 1.5 << "\n";
}
template
typename std::enable_if::value, void>::type
process(T value) {
std::cout << "Pointer: " << *value << "\n";
}
void sfinae_basic() {
process(42);
process(3.14);
int x = 100;
process(&x);
}
enable_if的返回类型位置。
template
auto half(T value) -> typename std::enable_if::value, T>::type {
return value / 2;
}
template
auto half(T value) -> typename std::enable_if::value, T>::type {
return value / 2.0;
}
void enable_if_return() {
std::cout << "Half int 10: " << half(10) << "\n";
std::cout << "Half double 10: " << half(10.0) << "\n";
}
enable_if在模板参数中。
template::value, int>::type = 0>
T add(T a, T b) {
return a + b;
}
void enable_if_param() {
std::cout << "add(3, 4): " << add(3, 4) << "\n";
std::cout << "add(2.5, 3.5): " << add(2.5, 3.5) << "\n";
}
检测类型是否有特定成员。
template
class has_size {
template
static auto test(int) -> decltype(std::declval().size(), std::true_type{});
template
static std::false_type test(...);
public:
static constexpr bool value = decltype(test(0))::value;
};
template
class has_iterator {
template
static auto test(int) -> decltype(std::declval().begin(), std::true_type{});
template
static std::false_type test(...);
public:
static constexpr bool value = decltype(test(0))::value;
};
void member_detection() {
std::cout << "vector has size: " << has_size>::value << "\n";
std::cout << "int has size: " << has_size::value << "\n";
std::cout << "vector has iterator: " << has_iterator>::value << "\n";
std::cout << "int has iterator: " << has_iterator::value << "\n";
}
enable_if实现类型特征。
template
struct EnableIf {};
template
struct EnableIf {
using type = T;
};
template
struct IsSame {
static constexpr bool value = false;
};
template
struct IsSame {
static constexpr bool value = true;
};
void custom_traits() {
static_assert(IsSame::value);
static_assert(!IsSame::value);
std::cout << "Custom traits work\n";
}
void conversion_type_traits() {
std::cout << "is_void_v: " << std::is_void_v << "\n";
std::cout << "is_array_v: " << std::is_array_v << "\n";
std::cout << "is_enum_v: " << std::is_enum_v << "\n";
std::cout << "is_class_v: " << std::is_class_v << "\n";
}
SFINAE can be used for tag dispatching.
template
void advanced_process(T value, std::true_type) {
std::cout << "Integer type: " << value * 2 << "\n";
}
template
void advanced_process(T value, std::false_type) {
std::cout << "Non-integer type: " << value << "\n";
}
template
void advanced_process(T value) {
advanced_process(value, std::is_integral{});
}
void tag_dispatch() {
advanced_process(42);
advanced_process(3.14);
advanced_process("hello");
}
void sfinae_with_decltype() {
auto lambda = [](auto& container) -> decltype(container[0]) {
return container[0];
};
std::vector vec = {10, 20, 30};
std::cout << "First element: " << lambda(vec) << "\n";
}
SFINAE是实现泛型类型检查和模板特化的重要技术,广泛应用于标准库实现中。