The SFINAE principle isn’t working for what seems really simple in Visual Studio 2010.
#include <type_traits>
#include <iostream>
struct MyStruct
{
int value;
MyStruct(int value = 42) : value(value) { }
const int& getInt() const { return value; }
};
template <typename ITER_TYPE>
auto getIteratorInt(ITER_TYPE iter) ->
typename std::enable_if
<std::is_pointer<decltype(*iter)>::value, const int&>::type
{
return (*iter)->getInt();
}
template <typename ITER_TYPE>
auto getIteratorInt(ITER_TYPE iter) ->
typename std::enable_if
<!std::is_pointer<decltype(*iter)>::value, const int&>::type
{
return iter->getInt();
}
int main(void)
{
MyStruct gloryInt;
MyStruct* gloryIntPtr = &gloryInt;
std::cout << getIteratorInt(gloryIntPtr) << std::endl;
std::cout << getIteratorInt(&gloryIntPtr) << std::endl;
return 0;
}
My intention is to use std::enable_if to compile the correct template overload based on the SFINAE principle. (The function without the existing return type will be ignored, and the other one will be compiled.) That way, you can use a pointer or a double pointer to an object, and the direct object will still be what is accessed.
I get the following compilation error:
main.cpp(14): error C2039: 'type' : is not a member of 'std::tr1::enable_if<_Test,_Type>'
with
[
_Test=false,
_Type=const int &
]
main.cpp(17): error C3646: 'type' : unknown override specifier
Well, this is a really obvious error to have if SFINAE wasn’t employed.
Is there any way to get the intended functionality in Visual Studio 2010?
Heh, should have checked your profile page before updating the other answer.
The type
decltype( * iter )refers toint const *const &, which is a reference to a pointer, not a “bare” pointer. Thereforestd::is_pointerreturns an unexpected result. There are two ways to solve this:Use
std::iterator_traitsfrom C++03, which I prefer:Use the
std::decaymetafunction which strips out referencesdecltypemight add to reflect the value category of the expression