The following traits classes are used to check whether a generic vector has operator[](int)
or 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{};
It seems to compile well in gcc 5.1.0
On the other hand, in the latest MSVC download (Microsoft Visual Studio Community 2015 RC Version 14.0.22823.1 D14REL), I get a compiler error for the has_parenthesis_operator
template which reads:
error C2064: term does not evaluate to a function taking 1 arguments
Moreover, the following version I find preferable do both not compile at all (note that operator[](int{})
is used instead of [int{}]
, and similar for the parenthesis):
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{};
The error message here is
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'
Questions:
- Is this a bug? Or am I doing something wrong (which gcc accepts somehow)?
- Is there a workaround by which I can use the above techniques (particularly
void_t
) - If a workaround is not possible, how to set up an alternate SFINAE check in MSVC (I tried much of this but didn't really succeed -- at least in in MSVC)?
As mentioned by @T.C., the above approach via
void_t<decltype(...)>
requires expression SFINAE, which is not available in the present version of MSVC 2015.Here is the current status on the implementation of expression SFINAE, taken from here:
Moreover, here is an a bit more old-fashioned workaround for the above traits using traditional SFINAE (inspired from here):
which can be used for example as
This checks whether the passed vector type has a member
double operator[](int)
, and if so calls it (--otherwise one can do similar with the parenthesis operator).Regardign the comment by @Yakk: I encountered the
__if_exists
statement special to MSVC which seems to fulfill a similar task than the above.