1

I'm trying to implement a conditional pointer dereferencing function. The basic idea is as follows:

return is_pointer(arg) ? *arg : arg

In order to limit the number of necessary specialization, I'm attempting to use rvalue references for the case where arg is not a pointer. Here is my current implementation (the std::cout are there solely for debugging purpose):

template< typename T >
inline typename std::enable_if< std::is_pointer< T >::value == false, T >::type deref(T&& t)
{
    std::cout << std::is_pointer< T >::value << std::endl;
    std::cout << typeid (T).name() << std::endl;
    return t;
}

template< typename T >
inline typename std::enable_if< std::is_pointer< T >::value == true, typename std::remove_pointer< T >::type& >::type deref(T t)
{
    std::cout << std::is_pointer< T >::value << std::endl;
    std::cout << typeid (T).name() << std::endl;
    return *t;
}

Now, I get a rather strange behavior under GCC 4.6. The first overload is used for both the non-pointer types and the pointer types. Obviously, when using a pointer type, it conflicts with the second overload. If I comment out the second one and call the following using the first one...

int q;
int *p = &q;
deref(p);

... the corresponding console output is:

0
Pi

How is it possible that a non-pointer type (according to std::is_pointer) is also a pointer type (according to typeid) in the same context? The conflict arises between both overloads due to std::is_pointer wrongly reporting p as a non-pointer type. Also, when I replace the r-value reference with a standard reference in the first overload:

inline typename std::enable_if< std::is_pointer< T >::value == false, T >::type deref(T& t)

It doesn't conflict with the second overload anymore... I simply don't get what's going on. By the way, using the second overload yields (as would be expected):

1
Pi

Thanks for your help.

4

2 に答える 2

3

私が理解する限りでは

template <T>
void foo(T&&)

が左辺値の場合T、それは参照として推定され(T = int*&あなたの場合)、参照の崩壊後にint*&&&通常の左辺値参照が生成されることを意味しますint*&。そうでない場合、この構文は何でも右辺値参照としてキャプチャします。ポイントは、左辺値を左辺値参照にバインドし、右辺値を右辺値参照にバインドすることです。

そして、is_pointer<int*&>そうではありません。したがって、適用してみてくださいremove_reference<T>

于 2011-02-11T21:00:46.297 に答える
2

最初のオーバーロードでは、T は int*& として推定されています。remove_reference<T>::typeenable_if-testing と出力で使用する最初のオーバーロードを試してください。

于 2011-02-11T20:56:09.943 に答える