SFINAE 检查 operator[] 比我还糊涂?
SFINAE check for operator[] is more confused than I am?
我为 operator[]
编写了简单的检查,但是 has_subscript_op
结构模板实例化选择了错误的重载:
#include <iostream>
#include <type_traits>
#include <string>
#include <map>
template<class, class, class = void>
struct has_subscript_op : std::false_type
{ };
template<class T, class S>
struct has_subscript_op<T, S, std::void_t<decltype(&std::declval<T>()[S()])>> : std::true_type
{ };
int main()
{
//true, nice
std::cout << "int[][int]: " << has_subscript_op<int[], int>::value << std::endl;
//false, nice
std::cout << "int[][float]: " << has_subscript_op<int[], float>::value << std::endl;
//true, nice
std::cout << "std::string[int]: " << has_subscript_op<std::string, int>::value << std::endl;
//true, WAT?
std::cout << "std::map<std::string, std::string>[int]: " << has_subscript_op<std::map<std::string, std::string>, int>::value << std::endl;
}
我正在使用 GCC 6.2.0
这是 GCC 错误,一般错误,还是我在某处犯了一个明显的错误?
只需删除 &
并使用 declval
作为密钥:
template<class T, class S>
struct has_subscript_op<T, S, std::void_t<decltype(std::declval<T>()[std::declval<S>()])>> : std::true_type {};
为什么 S()
的检查给出了错误的结果?因为在 GCC 中,它被认为是 0
。可以用指针构造一个std::string
,而0
恰好是一个空指针常量。
其他编译器不应像 C++14 中的 0
那样对待 S()
。
你可以自己试试:
std::map<std::string, std::string> test;
// compile fine, segfault at runtime
auto a = test[0];
// compile error!
auto b = test[2]
支票在 std::declval
上效果更好,因为它不是 0
,也不是 2
,而是普通的 int
。奖金,declval
,您的支票不需要默认可构造的密钥。
我为 operator[]
编写了简单的检查,但是 has_subscript_op
结构模板实例化选择了错误的重载:
#include <iostream>
#include <type_traits>
#include <string>
#include <map>
template<class, class, class = void>
struct has_subscript_op : std::false_type
{ };
template<class T, class S>
struct has_subscript_op<T, S, std::void_t<decltype(&std::declval<T>()[S()])>> : std::true_type
{ };
int main()
{
//true, nice
std::cout << "int[][int]: " << has_subscript_op<int[], int>::value << std::endl;
//false, nice
std::cout << "int[][float]: " << has_subscript_op<int[], float>::value << std::endl;
//true, nice
std::cout << "std::string[int]: " << has_subscript_op<std::string, int>::value << std::endl;
//true, WAT?
std::cout << "std::map<std::string, std::string>[int]: " << has_subscript_op<std::map<std::string, std::string>, int>::value << std::endl;
}
我正在使用 GCC 6.2.0
这是 GCC 错误,一般错误,还是我在某处犯了一个明显的错误?
只需删除 &
并使用 declval
作为密钥:
template<class T, class S>
struct has_subscript_op<T, S, std::void_t<decltype(std::declval<T>()[std::declval<S>()])>> : std::true_type {};
为什么 S()
的检查给出了错误的结果?因为在 GCC 中,它被认为是 0
。可以用指针构造一个std::string
,而0
恰好是一个空指针常量。
其他编译器不应像 C++14 中的 0
那样对待 S()
。
你可以自己试试:
std::map<std::string, std::string> test;
// compile fine, segfault at runtime
auto a = test[0];
// compile error!
auto b = test[2]
支票在 std::declval
上效果更好,因为它不是 0
,也不是 2
,而是普通的 int
。奖金,declval
,您的支票不需要默认可构造的密钥。