19

更具体地说,假设我正在写作template<class Pointer> class Foo,并且我想typedef在类中声明一个*p如果是 type 则将具有p的类型Pointer

据我所知,在 C++03 中,唯一的方法是使用类似

typename std::iterator_traits<Pointer>::reference

Pointer这种方法的缺点是,如果是一些自定义迭代器类型并且作者忘记扩展std::iterator或以其他方式定义std::iterator_traits专门化,它将不起作用。

在 C++11 中,我的同事建议

decltype(*Pointer())

但是,如果不是默认可构造的,这将不起作用Pointer,因此他将其修改为

decltype(**(Pointer*)0)

我试过这个,它奏效了,但后来我认为它看起来有点不确定,因为它涉及空指针的取消引用,因此可能不符合标准。

我们能做得更好吗?

4

4 回答 4

23

您对取消引用空指针保持谨慎是正确的,但事实是这里没问题!decltype不评估其操作数,因此在内部取消引用空指针是完全有效的。

然而,正确的解决方案是在 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 回答