SFINAE —— Substitution Failure Is Not An Error
IsConvertible
#include <iostream>
#include <string>
template <typename FROM, typename TO> struct IsConvetible {
// FROM should be converted to TO implicitly
static void aux(TO);
// Should use another typename F, otherwise it will cause an compilation error
// immediately
template <typename F, typename = decltype(aux(std::declval<F>()))>
static std::true_type test(void *);
// Will failed with: No viable conversion from 'double' to 'std::string'
// template <typename = decltype(aux(std::declval<FROM>()))>
// static std::true_type test(void *);
// If the above function failed, it will fallback here
template <typename> static std::false_type test(...);
static constexpr bool value = decltype(test<FROM>(nullptr))::value;
};
int main() {
std::cout << std::boolalpha;
std::cout << IsConvetible<double, std::string>::value << std::endl;
std::cout << IsConvetible<double, int>::value << std::endl;
std::cout << IsConvetible<const char *, std::string>::value << std::endl;
std::cout << IsConvetible<const char[10], std::string>::value << std::endl;
std::cout << IsConvetible<char[10], std::string>::value << std::endl;
}
输出:
false
true
true
true
true
IsDefaultConstructible
#include <iostream>
#include <string>
template <typename T> struct IsDefaultConstructibleHelper {
// Should use another typename U, otherwise it will cause an compilation error
// immediately
template <typename U, typename = decltype(U())>
static std::true_type test(void *);
// If the above function failed, it will fallback here.
template <typename> static std::false_type test(...);
static constexpr bool value = decltype(test<T>(nullptr))::value;
};
template <typename T>
constexpr bool IsDefaultConstructible = IsDefaultConstructibleHelper<T>::value;
class WithDefaultConstructor {};
class WithoutDefaultConstructor {
WithoutDefaultConstructor() = delete;
};
int main() {
std::cout << std::boolalpha;
std::cout << IsDefaultConstructible<int> << std::endl;
std::cout << IsDefaultConstructible<WithDefaultConstructor> << std::endl;
std::cout << IsDefaultConstructible<WithoutDefaultConstructor> << std::endl;
}
输出:
true
true
false