SFINAE 为什么我没有检测到 std::vector 的下标运算符?
SFINAE Why am I not detecting std::vector's subscript operator?
我写了一些模板元废话来检测 class 方法是否存在。
模板结构 has_subscript
是专门的,因此如果第一个模板参数具有下标运算符,则第二个模板参数为 void
。如果找到下标运算符,则使用特化版本,否则 SFINAE 默认为非特化版本。
我的代码适用于一个简单的 struct foo(它的模板化只是为了更好地匹配 std::vector
),但它意外地失败了 std::vector
。
演示 link https://godbolt.org/z/5-QzAp
#include <type_traits>
#include <iostream>
#include <vector>
using namespace std;
template <typename>
struct void_wrap
{ using type = void; };
template <typename T, typename = void>
struct has_subscript
{
static constexpr bool value = false;
};
template <typename T>
struct has_subscript <T, typename void_wrap<typename result_of<decltype(&T::operator[])(T,int)>::type>::type >
{
static constexpr bool value = true;
};
template <typename T>
struct foo
{
double operator[](size_t x){return 0.0;}
};
int main()
{
cout << has_subscript<foo<int>>::value;
cout << has_subscript<vector<int>>::value;
}
您可以使用 库基础 TS v2 中的 std::is_detected
。
#include <type_traits>
#include <experimental/type_traits>
#include <vector>
template<typename T>
using bracket_op_t = decltype( std::declval<T&>()[0] );
template<typename T>
constexpr bool has_bracket_op = std::experimental::is_detected<bracket_op_t, T>::value;
int main()
{
// static_assert(has_bracket_op<int>, ""); // fails to compile
static_assert(has_bracket_op<std::vector<int>>, "");
}
LIVE DEMO
它与您尝试推断 operator[]
的方式有关,它适用于 foo
但不适用于 std::vector
,因为它已过载。
无法使用表达式 typename result_of<decltype(&T::operator[])(T,int)>::type
,因为 &T::operator[]
不明确。
如果您使用 decltype(std::declval<T&>()[int()])
,那么它将按预期工作(参见 here)。
我写了一些模板元废话来检测 class 方法是否存在。
模板结构 has_subscript
是专门的,因此如果第一个模板参数具有下标运算符,则第二个模板参数为 void
。如果找到下标运算符,则使用特化版本,否则 SFINAE 默认为非特化版本。
我的代码适用于一个简单的 struct foo(它的模板化只是为了更好地匹配 std::vector
),但它意外地失败了 std::vector
。
演示 link https://godbolt.org/z/5-QzAp
#include <type_traits>
#include <iostream>
#include <vector>
using namespace std;
template <typename>
struct void_wrap
{ using type = void; };
template <typename T, typename = void>
struct has_subscript
{
static constexpr bool value = false;
};
template <typename T>
struct has_subscript <T, typename void_wrap<typename result_of<decltype(&T::operator[])(T,int)>::type>::type >
{
static constexpr bool value = true;
};
template <typename T>
struct foo
{
double operator[](size_t x){return 0.0;}
};
int main()
{
cout << has_subscript<foo<int>>::value;
cout << has_subscript<vector<int>>::value;
}
您可以使用 库基础 TS v2 中的 std::is_detected
。
#include <type_traits>
#include <experimental/type_traits>
#include <vector>
template<typename T>
using bracket_op_t = decltype( std::declval<T&>()[0] );
template<typename T>
constexpr bool has_bracket_op = std::experimental::is_detected<bracket_op_t, T>::value;
int main()
{
// static_assert(has_bracket_op<int>, ""); // fails to compile
static_assert(has_bracket_op<std::vector<int>>, "");
}
LIVE DEMO
它与您尝试推断 operator[]
的方式有关,它适用于 foo
但不适用于 std::vector
,因为它已过载。
无法使用表达式 typename result_of<decltype(&T::operator[])(T,int)>::type
,因为 &T::operator[]
不明确。
如果您使用 decltype(std::declval<T&>()[int()])
,那么它将按预期工作(参见 here)。