以下特征类用于检查通用矢量是否具有operator[](int)
或operator()(int)
:
template<typename ...> using void_t = void;
template< typename, typename = void>
struct has_bracket_operator : public std::false_type {};
template<typename V>
struct has_bracket_operator<V, void_t<decltype(std::declval<V>()[int{}])> >
: public std::true_type{};
template<typename, typename = void>
struct has_parenthesis_operator : public std::false_type {};
template<typename V>
struct has_parenthesis_operator<V, void_t<decltype(std::declval<V>()(int{}))> >
: public std::true_type{};
另一方面,在最新的MSVC下载( Microsoft Visual Studio Community 2015 RC版本14.0.22823.1 D14REL )中,我收到has_parenthesis_operator
模板的编译器错误,其中包含:
error C2064: term does not evaluate to a function taking 1 arguments
此外,以下我认为最好的版本都不会编译(注意operator[](int{})
代替[int{}]
,类似于括号):
template<typename V>
struct has_bracket_operator<V, void_t<decltype(std::declval<V>().operator[](int{}))> >
: public std::true_type{};
//...
template<typename V>
struct has_parenthesis_operator<V, void_t<decltype(std::declval<V>().operator()(int{}))> >
: public std::true_type{};
这里的错误信息是
error C2228: left of '.[]' must have class/struct/union note: type is 'add_rvalue_reference<V>::type' error C2228: left of '.()' must have class/struct/union note: type is 'add_rvalue_reference<V>::type'
问题:
void_t
)答案 0 :(得分:0)
正如@ T.C。所述,上述方法void_t<decltype(...)>
需要expression SFINAE,这在当前版本的MSVC 2015中不可用。
以下是表达式SFINAE的实现状态,取自here:
Q值。你什么时候实施表达SFINAE?
一个。我们正计划开始实施表达SFINAE 2015 RTM之后立即编译,我们正计划交付它 在2015年更新中,支持生产使用。 (但不是 必然2015年更新1.可能需要更长时间。)
要清楚,这仅适用于编译器,而不适用于编译器 库。 C ++ 11标准库强制要求使用Expression SFINAE在少数几个地方,我们已经实际上已经存在 实现。 (这些地方是is_assignable和allocator_traits, 编译器特别注意支持。)C ++ 14 标准库增加了两个表达SFINAE必须的地方 used:std :: function construction / assignment和result_of。我&#39; 11 编译器准备好后修改STL,但我不打算这样做 在更新中发送这些库更改。 ...
此外,对于使用传统SFINAE(灵感来自here)的上述特征,这里有一个有点更老式的解决方法:
template<typename C, typename Ret, typename... Args>
struct has_parenthesis_operator<C, Ret(Args...)>
{
private:
template<typename T>
static constexpr auto check(T*)
-> typename std::is_same<std::decay_t<decltype(std::declval<T>().operator()(std::declval<Args>()...))>, Ret>::type;
template<typename> static constexpr std::false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static constexpr bool value = type::value;
};
可以用作例如
template<typename V
, typename = std::enable_if_t<has_bracket_operator<V, double(int)>::value>
auto get(V const& v, int i)
{
return v[i];
}
检查传递的矢量类型是否有成员double operator[](int)
,如果是,则调用它( - 另外一个可以用括号运算符表示)。
通过@Yakk来评论评论:我遇到了MSVC的__if_exists
statement特殊功能,它似乎完成了与上述类似的任务。