19

To be more specific, suppose I am writing template<class Pointer> class Foo and I want to declare a typedef inside the class for the type that *p would have if p were of type Pointer.

In C++03, as far as I am aware, the only way to do this is with something like

typename std::iterator_traits<Pointer>::reference

The disadvantage of this method is that it won't work if Pointer is some custom iterator type and the author forgot to extend std::iterator or otherwise define a std::iterator_traits specialization.

In C++11, my colleague suggested

decltype(*Pointer())

But this won't work if Pointer is not default-constructible, so he amended this to

decltype(**(Pointer*)0)

I tried this, and it worked, but then I thought that it looked a bit iffy because it involves the dereference of a null pointer, and thus might not be standards-compliant.

Can we do better?

4

4 に答える 4

23

null ポインターの逆参照に注意するのは正しいことですが、実際のところ、ここでは問題ありません。decltypeはそのオペランドを評価しないため、内部の null ポインターを逆参照することは完全に有効です。

ただし、適切な解決策は、 C++ 11 でstd::declval内部に導入されたものです。<utility>

decltype(*std::declval<Pointer>())
于 2013-01-23T01:56:49.983 に答える
3

C++03 では、指定された型からすべてのポインターを削除する単純な構造を作成できます。

template<typename T>
struct ActualType { typedef T type; };
template<typename T>
struct ActualType<T*> { typedef typename ActualType<T>::type type; };

あなたが合格した場合、int*またはint**最終的にはActualType<T>::typeに要約されintます。

これがデモです。

于 2013-01-23T02:59:31.457 に答える
0

SFINAE逆参照へのフォールバックで反復子の特性を実行します。

null を逆参照するのではなく、返すテンプレート関数を作成してstd::decay<T>&から逆参照します。

于 2013-01-23T02:00:01.547 に答える
0

C++11 では、次を使用できます。std::pointer_type

using PType = std::pointer_type<Pointer>::type;
于 2021-04-30T04:18:08.933 に答える