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条答案
按热度按时间osh3o9ms1#
你对空指针的解引用非常谨慎是对的,但事实上这里是可以的!
decltype
不计算它的操作数,所以在里面解引用空指针是完全有效的。然而,正确的解决方案是
std::declval
,它是在C++11中的<utility>
中引入的:kuhbmx9i2#
在C++03中,你可以写一个简单的构造,它将从给定的类型中删除所有的指针:
如果你传递
int*
或int**
,那么最后ActualType<T>::type
将归结为int
。这里是demo;
brccelvz3#
在C++11中,可以使用
std::remove_pointer
bvjxkvbb4#
使用
SFINAE
回退到取消引用来执行迭代器特性。创建一个返回
std::decay<T>&
的模板函数,然后对它进行解引用,而不是解引用null。