更具体地说,假设我正在撰写template<class Pointer> class Foo
,并且我想在类中声明typedef
类型*p
如果p
属于输入Pointer
。
在C ++ 03中,据我所知,唯一的方法是使用类似
的方法typename std::iterator_traits<Pointer>::reference
此方法的缺点是,如果Pointer
是某个自定义迭代器类型且作者忘记扩展std::iterator
或以其他方式定义std::iterator_traits
专门化,则它将无效。
在C ++ 11中,我的同事建议
decltype(*Pointer())
但是如果Pointer
不是默认可构造的,那么这将不起作用,所以他将其修改为
decltype(**(Pointer*)0)
我尝试了这个,但它确实有效,但后来我认为它看起来有点不确定因为它涉及空引用的解引用,因此可能不符合标准。
我们可以做得更好吗?
答案 0 :(得分:22)
你对解除引用空指针持谨慎态度,但事实是它在这里没关系! <{1}}不评估其操作数,因此在内部取消引用空指针是完全有效的。
然而,正确的解决方案是decltype
,在C ++ 11中的std::declval
中引入:
<utility>
答案 1 :(得分:2)
在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
。
这是demo;
答案 2 :(得分:0)
执行具有SFINAE
回退的迭代器特征以解除引用。
创建一个返回std::decay<T>&
然后取消引用的模板函数,而不是取消引用null。
答案 3 :(得分:0)
在 C++11 中,您可以使用 std::pointer_type
using PType = std::pointer_type<Pointer>::type;