SFINAE:删除具有相同原型的函数
SFINAE : Delete a function with the same prototype
我想知道这段有效代码之间有什么区别:
#include <type_traits>
#include <iostream>
template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;
template<typename T, is_ref<T> = true>
void foo(T&&) {
std::cout << "ref" << std::endl;
}
template<typename T, is_not_ref<T> = true>
void foo(T&&) {
std::cout << "not ref" << std::endl;
}
int main() {
int a = 0;
foo(a);
foo(5);
}
还有这个不起作用:
#include <type_traits>
#include <iostream>
template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;
template<typename T, typename = is_ref<T>>
void foo(T&&) {
std::cout << "ref" << std::endl;
}
template<typename T, typename = is_not_ref<T>>
void foo(T&&) {
std::cout << "not ref" << std::endl;
}
int main() {
int a = 0;
foo(a);
foo(5);
}
typename = is_ref<T>
和 is_ref<T> = true
之间的真正区别是什么?
如果您删除默认的模板参数,就会清楚其中的区别。函数声明不能只是它们的默认值不同。这是错误的格式:
void foo(int i = 4);
void foo(int i = 5);
同样这是错误的:
template <typename T=int> void foo();
template <typename T=double> void foo();
考虑到这一点,您的第一个案例:
template<typename T, is_ref<T>>
void foo(T&&);
template<typename T, is_not_ref<T>>
void foo(T&&);
这里的两个声明是唯一的,因为第二个模板参数在两个声明之间是不同的。第一个有一个类型为 std::enable_if_t<std::is_reference_v<T>, bool>
的非类型模板参数,第二个有一个类型为 std::enable_if_t<!std::is_reference_v<T>, bool>
的非类型模板参数。这些是不同的类型。
鉴于,您的第二种情况:
template<typename T, typename>
void foo(T&&);
template<typename T, typename>
void foo(T&&)
这显然是同一个签名 - 但我们只是复制了它。这是错误的格式。
我想知道这段有效代码之间有什么区别:
#include <type_traits>
#include <iostream>
template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;
template<typename T, is_ref<T> = true>
void foo(T&&) {
std::cout << "ref" << std::endl;
}
template<typename T, is_not_ref<T> = true>
void foo(T&&) {
std::cout << "not ref" << std::endl;
}
int main() {
int a = 0;
foo(a);
foo(5);
}
还有这个不起作用:
#include <type_traits>
#include <iostream>
template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;
template<typename T, typename = is_ref<T>>
void foo(T&&) {
std::cout << "ref" << std::endl;
}
template<typename T, typename = is_not_ref<T>>
void foo(T&&) {
std::cout << "not ref" << std::endl;
}
int main() {
int a = 0;
foo(a);
foo(5);
}
typename = is_ref<T>
和 is_ref<T> = true
之间的真正区别是什么?
如果您删除默认的模板参数,就会清楚其中的区别。函数声明不能只是它们的默认值不同。这是错误的格式:
void foo(int i = 4);
void foo(int i = 5);
同样这是错误的:
template <typename T=int> void foo();
template <typename T=double> void foo();
考虑到这一点,您的第一个案例:
template<typename T, is_ref<T>>
void foo(T&&);
template<typename T, is_not_ref<T>>
void foo(T&&);
这里的两个声明是唯一的,因为第二个模板参数在两个声明之间是不同的。第一个有一个类型为 std::enable_if_t<std::is_reference_v<T>, bool>
的非类型模板参数,第二个有一个类型为 std::enable_if_t<!std::is_reference_v<T>, bool>
的非类型模板参数。这些是不同的类型。
鉴于,您的第二种情况:
template<typename T, typename>
void foo(T&&);
template<typename T, typename>
void foo(T&&)
这显然是同一个签名 - 但我们只是复制了它。这是错误的格式。