gpt4 book ai didi

c++ - 如何检查下标运算符是否存在?

转载 作者:可可西里 更新时间:2023-11-01 15:56:54 28 4
gpt4 key购买 nike

我想编写一个类型特征,它使用 SFINAE 检查类型是否存在下标表达式。我在下面的初步尝试似乎在下标表达式可能时有效,但在括号运算符不存在时无效。

#include <iostream>
#include <vector>
#include <cassert>

template<class T, class Index>
struct has_subscript_operator_impl
{
template<class T1,
class Reference = decltype(
(*std::declval<T*>())[std::declval<Index>()]
),
class = typename std::enable_if<
!std::is_void<Reference>::value
>::type>
static std::true_type test(int);

template<class>
static std::false_type test(...);

using type = decltype(test<T>(0));
};


template<class T, class Index>
using has_subscript_operator = typename has_subscript_operator_impl<T,Index>::type;

struct doesnt_have_it {};

struct returns_void
{
void operator[](int) {}
};

struct returns_int
{
int operator[](int) { return 0; }
};

int main()
{
std::cout << "has_subscript_operator<doesnt_have_it,int>: " << has_subscript_operator<doesnt_have_it,int>::value << std::endl;
assert((!has_subscript_operator<doesnt_have_it,int>::value));

std::cout << "has_subscript_operator<returns_void,int>: " << has_subscript_operator<returns_void,int>::value << std::endl;
assert((!has_subscript_operator<returns_void,int>::value));

std::cout << "has_subscript_operator<returns_int,int>: " << has_subscript_operator<returns_int,int>::value << std::endl;
assert((has_subscript_operator<returns_int,int>::value));

std::cout << "has_subscript_operator<int*,int>: " << has_subscript_operator<int*,int>::value << std::endl;
assert((has_subscript_operator<int*,int>::value));

std::cout << "has_subscript_operator<std::vector<int>,int>: " << has_subscript_operator<std::vector<int>,int>::value << std::endl;
assert((has_subscript_operator<returns_int,int>::value));

return 0;
}

clang-3.4 的输出:

$ clang -std=c++11 -I. -lstdc++ test_has_subscript_operator.cpp 
test_has_subscript_operator.cpp:10:14: error: type 'doesnt_have_it' does not provide a subscript operator
(*std::declval<T*>())[std::declval<Index>()]
^~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
test_has_subscript_operator.cpp:25:1: note: in instantiation of template class 'has_subscript_operator_impl<doesnt_have_it, int>' requested here
using has_subscript_operator = typename has_subscript_operator_impl<T,Index>::type;
^
test_has_subscript_operator.cpp:41:66: note: in instantiation of template type alias 'has_subscript_operator' requested here
std::cout << "has_subscript_operator<doesnt_have_it,int>: " << has_subscript_operator<doesnt_have_it,int>::value << std::endl;
^
1 error generated.

如何修复我的 has_subscript_operator 使其适用于所有类型?

最佳答案

SFINAE 仅在直接上下文中发生替换失败时才起作用。在实例化成员函数模板 test 时,模板参数 Index 已经已知,因此您不会遇到替换失败,而是遇到硬错误。

解决这个问题的技巧是通过向 test 添加一个额外的模板类型参数并将其默认为 Index 来再次推导出 Index

template<class T1,
class IndexDeduced = Index, // <--- here
class Reference = decltype(
(*std::declval<T*>())[std::declval<IndexDeduced>()] // and use that here
),
class = typename std::enable_if<
!std::is_void<Reference>::value
>::type>
static std::true_type test(int);

现在您的代码按预期工作。

Live demo

关于c++ - 如何检查下标运算符是否存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31305894/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com