SFINAE 和函数重载时的隐式转换
SFINAE and implicit cast while function overloading
我正在尝试编写一个模板助手,让我检查一组类型是否与结构成员的类型相匹配。到目前为止我已经写了这个 -
#include <iostream>
#include <functional>
struct foo {
int field1;
int field2;
};
template <typename...T, std::size_t ...indices >
constexpr bool construct (std::index_sequence<indices...>) {
foo s = {std::get<indices>(std::tuple<T...>())...};
return true;
}
template<typename...T>
static bool allowed(int) {
construct<T...>(std::index_sequence_for<T...>());
return true;
}
template<typename...T>
static bool allowed(long) {
return false;
}
int main() {
std::cout << allowed<int, int, int>(0);
return 0;
}
这里,显然对allowed<int, int, int>
的调用是无效的,因为无法调用构造(foo有2个成员,它正在用3个成员初始化)。但是还有另一种 allowed 实现,它以 long
作为参数。自SFINAE以来,编译器不应该简单地匹配allowed和return false
的第二个模板实现吗?但它反而给了我一个错误 -
error: too many initializers for ‘foo’
foo s = {std::get<indices>(std::tuple<T...>())...};
如果我只是注释掉 allowed 的第一个实现,一切都很好,但我得到了一个 false。我很困惑w.r.t。模板替换如何与隐式转换和函数重载交互。如果不允许,有什么方法可以达到同样的效果吗?
foo
不在直接上下文中,因此您会遇到硬错误而不是 SFINAE。
考虑一下:
#include <iostream>
#include <functional>
struct foo {
int field1;
int field2;
};
template <typename U, typename...T, std::size_t ...indices >
constexpr auto construct (std::index_sequence<indices...>) -> decltype(new U {std::get<indices>(std::tuple<T...>())...}) {
return nullptr;
}
template<typename...T, typename Q = decltype(construct<foo, T...>(std::index_sequence_for<T...>()))>
static bool allowed(int) {
return true;
}
template<typename...T>
static bool allowed(long) {
return false;
}
int main() {
std::cout << "allowed<int,int>(0) = " << allowed<int,int>(0) << std::endl;
std::cout << "allowed<int,int,int>(0) = " << allowed<int,int,int>(0) << std::endl;
return 0;
}
我正在尝试编写一个模板助手,让我检查一组类型是否与结构成员的类型相匹配。到目前为止我已经写了这个 -
#include <iostream>
#include <functional>
struct foo {
int field1;
int field2;
};
template <typename...T, std::size_t ...indices >
constexpr bool construct (std::index_sequence<indices...>) {
foo s = {std::get<indices>(std::tuple<T...>())...};
return true;
}
template<typename...T>
static bool allowed(int) {
construct<T...>(std::index_sequence_for<T...>());
return true;
}
template<typename...T>
static bool allowed(long) {
return false;
}
int main() {
std::cout << allowed<int, int, int>(0);
return 0;
}
这里,显然对allowed<int, int, int>
的调用是无效的,因为无法调用构造(foo有2个成员,它正在用3个成员初始化)。但是还有另一种 allowed 实现,它以 long
作为参数。自SFINAE以来,编译器不应该简单地匹配allowed和return false
的第二个模板实现吗?但它反而给了我一个错误 -
error: too many initializers for ‘foo’
foo s = {std::get<indices>(std::tuple<T...>())...};
如果我只是注释掉 allowed 的第一个实现,一切都很好,但我得到了一个 false。我很困惑w.r.t。模板替换如何与隐式转换和函数重载交互。如果不允许,有什么方法可以达到同样的效果吗?
foo
不在直接上下文中,因此您会遇到硬错误而不是 SFINAE。
考虑一下:
#include <iostream>
#include <functional>
struct foo {
int field1;
int field2;
};
template <typename U, typename...T, std::size_t ...indices >
constexpr auto construct (std::index_sequence<indices...>) -> decltype(new U {std::get<indices>(std::tuple<T...>())...}) {
return nullptr;
}
template<typename...T, typename Q = decltype(construct<foo, T...>(std::index_sequence_for<T...>()))>
static bool allowed(int) {
return true;
}
template<typename...T>
static bool allowed(long) {
return false;
}
int main() {
std::cout << "allowed<int,int>(0) = " << allowed<int,int>(0) << std::endl;
std::cout << "allowed<int,int,int>(0) = " << allowed<int,int,int>(0) << std::endl;
return 0;
}