Reputation: 45
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?
Upvotes: 1
Views: 846
Reputation: 137830
Heh, should have checked your profile page before updating the other answer.
The type decltype( * iter )
refers to int const *const &
, which is a reference to a pointer, not a "bare" pointer. Therefore std::is_pointer
returns an unexpected result. There are two ways to solve this:
Use std::iterator_traits
from C++03, which I prefer:
typename std::iterator_traits< ITER_TYPE >::value_type
Use the std::decay
metafunction which strips out references decltype
might add to reflect the value category of the expression
typename std::decay< decltype( * iter ) >::type
Upvotes: 2