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是实现泛型类型检查和模板特化的重要技术,广泛应用于标准库实现中。