为何无法用std::add_rvalue_reference<T>::type直接替代std::declval?
问题:为什么用
std::add_rvalue_reference<Test>::type替代std::declval<T>()会编译失败? 根据cppreference的说明,std::declval的一种可能实现如下:
template<typename T> constexpr bool always_false = false; template<typename T> typename std::add_rvalue_reference<T>::type declval() noexcept { static_assert(always_false<T>, "declval not allowed in an evaluated context"); }
我尝试用std::add_rvalue_reference<Test>::type替代std::declval<T>()的用法,但编译失败,测试代码如下:
#include <iostream> #include <type_traits> #include <utility> struct Test { int func() { return 1; } }; template<typename T> constexpr bool always_false = false; template<typename T> typename std::add_rvalue_reference<T>::type Decltype() noexcept { static_assert(always_false<T>, "declval not allowed in an evaluated context"); } int main() { if (std::is_same_v<decltype(std::add_rvalue_reference<Test>::type.func()),int>) { std::cout <<"same\n"; } else { std::cout <<"different\n"; } }
原因分析
std::add_rvalue_reference<Test>::type是类型名称,不是可执行的表达式。C++语法不允许直接对类型调用成员函数——你必须拥有该类型的对象(或能产生该类型值的表达式)才能调用成员函数。std::declval<T>()本质是一个函数模板,它的返回值类型确实是std::add_rvalue_reference<T>::type,但关键在于它是一个函数调用表达式。在decltype中,这个表达式不需要被实际执行(decltype仅用于分析表达式的类型),所以函数体里的static_assert永远不会触发,但编译器能通过这个表达式生成一个合法的右值引用类型"对象",进而允许你调用成员函数。
修正方案
方案1:使用自定义的Decltype函数调用
把代码里的std::add_rvalue_reference<Test>::type替换成Decltype<Test>(),用函数调用表达式生成合法的右值引用类型:
#include <iostream> #include <type_traits> #include <utility> struct Test { int func() { return 1; } }; template<typename T> constexpr bool always_false = false; template<typename T> typename std::add_rvalue_reference<T>::type Decltype() noexcept { static_assert(always_false<T>, "declval not allowed in an evaluated context"); } int main() { if (std::is_same_v<decltype(Decltype<Test>().func()), int>) { std::cout << "same\n"; } else { std::cout << "different\n"; } }
方案2:直接使用标准库的std::declval
直接用标准库提供的std::declval更简洁:
#include <iostream> #include <type_traits> #include <utility> struct Test { int func() { return 1; } }; int main() { if (std::is_same_v<decltype(std::declval<Test>().func()), int>) { std::cout << "same\n"; } else { std::cout << "different\n"; } }
内容的提问来源于stack exchange,提问作者cpp
相关产品推荐
相关产品推荐

