C++ - 具有右值引用的函数模板特化行为

标签 c++ c++11 template-specialization rvalue-reference enable-if

我正在尝试实现一个条件指针解引用函数。基本思路如下:

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 报告为非指针类型,两个重载之间出现了冲突。此外,当我在第一个重载中用标准引用替换右值引用时:

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

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

1
Pi

感谢您的帮助。

最佳答案

据我所知

template <T>
void foo(T&&)

表示如果 T是左值,它将被推断为引用(在您的情况下为 T = int*&)并且在引用折叠 int*&&& 之后产生一个常规的左值引用 int*& .如果不是那样,此语法会将任何内容捕获为右值引用。而重点是将左值绑定(bind)到左值引用,将右值绑定(bind)到右值引用。

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

关于C++ - 具有右值引用的函数模板特化行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4973776/

相关文章:

c++ - 如何在 sf::RectangleShape 中居中 sf::Text

c++ - 我可以继承 C++11 中的构造函数并初始化一些额外的东西而不必重写构造函数吗?

c++ - OpenCV 错误 : Assertion failed ((img. depth() == CV_8U || img.depth() == CV_32F)

c++ - 将可变参数模板传递给 pthread_create

c++ - 代码重复和模板特化(当特化函数有不同的返回类型时)

c++ - 快速选择算法

c - 什么时候可以将原子读取-修改-写入操作分解为组成宽松的操作+屏障?

c++ - 如何在 C++ 中进行从枚举到类型的转换(并在模板中使用)?

c++ - 我可以将 std::begin 和 std::end 专门化为 equal_range() 的返回值吗?

c++ - 为什么编译器不会停止在此模板代码上出错