如何获取std::declval<T>()的指针?编译报错问题咨询
如何获取std::declval()的指针?编译报错问题咨询
嘿,我来帮你拆解下这个编译报错的问题。先看看你给出的这段代码:
template <typename T> void test_serialisation(T* t) { constexpr bool can_serialise = requires { t->doesntexist; }; } template <typename T> void something() { test_serialisation(&std::declval<T>()); // HERE 编译报错 } int main(int argc, char* argv[]) { something<int>(); }
你遇到的错误提示“地址操作符的操作数必须是左值”,本质原因是**std::declval<T>()返回的是右值(准确说是xvalue,即亡值)**,而C++里取地址运算符&只能作用于左值,直接对declval的结果取地址自然会触发编译错误。
那怎么解决呢?其实调整下declval的模板参数就行——我们需要让它返回左值引用,只需要把模板参数改成T&,也就是使用std::declval<T&>()。修改后的something函数如下:
template <typename T> void something() { test_serialisation(&std::declval<T&>()); // 这里改成T&即可 }
为什么这样能行?因为std::declval是个模板函数,当你传入T&作为模板参数时,根据C++的引用折叠规则,它的返回值会变成T&(左值引用),左值是允许被取地址的,这样就完全匹配test_serialisation对T*参数的要求了。
补充个小知识点:std::declval本来就是为了在不求值的上下文(比如requires表达式、sizeof计算)里模拟对象的存在,通过指定不同的引用类型,我们可以灵活模拟出左值或右值的“虚拟对象”。你这里需要取地址,所以必须模拟出左值,用T&作为参数传递给declval就刚好能满足需求。
内容来源于stack exchange
相关产品推荐
相关产品推荐

