我们如何测试是否可以使用 prvalue 调用某种类型的表达式
How do we test if an expression of a certain type can be invoked with a prvalue?
使用 c++17,我们有花哨的新is_invocable
和花哨的新 prvalues 不是真正的值。
这允许您创建一个对象,而不必先在逻辑上构造它,然后省略构造。
我遇到了一个问题,使用 std::is_invocable
来测试是否可以调用某些东西,并且 prvalue 规则似乎发生了冲突:
struct no_move {
no_move(no_move&&)=delete;
explicit no_move(int) {}
};
void f( no_move ) {}
现在我们可以问一下是否可以使用 no_move
类型的 prvalue 调用f
?
f( no_move(1) )
std::is_invocable< decltype(&f), no_move >
不起作用,因为它使用std::declval<no_move>()
,这是一个像no_move&&
而不是 no_move
类型的 prvalue 。
在 c++14 中,这是相同的,但保证省略使某些函数可以使用 xvalue (即 "T&&
"( 调用,而其他函数可以使用 T
类型的 prvalues 调用。
有没有其他选择,或者我们必须发明自己的特质来处理这种情况?
(在一个理论世界中,std::declval<T>
返回T
而不是T&&
,我相信is_invocable
会做正确的事情(。
您滥用了 Invocable 概念。这个概念只意味着在给定函数和提供的参数上使用std::invoke
的能力。
你不能做std::invoke(f, no_move(1))
,因为这会引发转发参数的复制/移动。通过像 invoke
这样的转发调用将 prvalue 用作参数是不可能的。您可以将 prvalue 传递给转接调用,但对给定函数的最终调用将获得一个 xvalue。
这是避免在函数中使用 immobile 类型作为值参数的一个很好的理由。取而代之的是const&
。
C++没有类型特征来查看是否可以以您想要的方式使用特定参数调用函数。
有没有其他选择,或者我们必须发明自己的特质来处理这种情况?
是的,你只需要写你自己的不使用declval
的特征。假设你有std::is_detected
躺着(我知道你肯定有(:
template <typename T> T make();
template <typename F, typename... Args>
using invoke_result_t = decltype(std::declval<F>()(make<Args>()...));
// ^^^^^^^^^^^^^ ^^^^^
template <typename F, typename... Args>
using is_invocable = std::is_detected<invoke_result_t, F, Args...>;
这样,std::is_invocable<decltype(f), no_move>
false_type
,但is_invocable<decltype(f), no_move)>
true_type
。
我故意将declval<F>()
用于函数而不是make
,以便允许在此处使用decltype(f)
。真的,invoke_result_t
应该更复杂,并且"做正确的事"来指向成员等。但这至少是一个简单的近似值,表明这种方法的可行性。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- 返回指向对象的指针的函数调用是否为 prvalue?
- 我们如何测试是否可以使用 prvalue 调用某种类型的表达式