1

我正在尝试实现条件指针取消引用功能。基本思路如下:

return is_pointer(arg) ? *arg : arg

为了限制必要专业化的数量,我尝试在arg不是指针的情况下使用右值引用。这是我当前的实现(std::cout仅用于调试目的):

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;
}

现在,我在 GCC 4.6 下得到了一个相当奇怪的行为。第一个重载用于非指针类型和指针类型。显然,当使用指针类型时,它与第二个重载冲突。如果我注释掉第二个并使用第一个调用以下...

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

...相应的控制台输出为:

0
Pi

在同一上下文中,非指针类型(根据std::is_pointer)怎么可能也是指针类型(根据)?typeid由于std::is_pointer错误地报告p为非指针类型,两个重载之间会出现冲突。此外,当我在第一次重载中将 r 值引用替换为标准引用时:

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

它不再与第二次重载冲突......我只是不明白发生了什么。顺便说一句,使用第二个重载会产生(正如预期的那样):

1
Pi

谢谢你的帮助。

4

2 回答 2

3

据我所理解

template <T>
void foo(T&&)

意味着 ifT是一个左值,它将被推断为一个引用(T = int*&在你的情况下),并且在引用折叠后int*&&&产生一个常规的左值引用int*&。如果不是这样,此语法将捕获任何内容作为右值引用。而关键是将左值绑定到左值引用,将右值绑定到右值引用。

而且is_pointer<int*&>不是真的。因此,您可以尝试申请remove_reference<T>.

于 2011-02-11T21:00:46.297 回答
2

在您的第一个重载中,T 被推断为 int*&。尝试在您的第一个重载中使用remove_reference<T>::type您的 enable_if-testing 和输出。

于 2011-02-11T20:56:09.943 回答