Yak*_*ont 15 c++ c++17 prvalue declval invocable
使用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 ) {}
Run Code Online (Sandbox Code Playgroud)
现在我们可以问一下是否f
可以使用类型的prvalue调用no_move
?
f( no_move(1) )
Run Code Online (Sandbox Code Playgroud)
std::is_invocable< decltype(&f), no_move >
不起作用,因为它使用的std::declval<no_move>()
是xvalue,no_move&&
而不是类型的prvalue no_move
.
在c ++ 14中,这是相同的,但保证省略使得一些函数可以用xvalue(即" T&&
")调用,而其他函数可以用prvalues类型调用T
.
有替代方案,还是我们必须发明自己的特性来处理这种情况?
(在一个理论的世界里std::declval<T>
返回T
,而不是T&&
,is_invocable
会的,我相信,做正确的事).
您滥用Invocable概念.这个概念仅仅意味着std::invoke
在给定函数和提供的参数上使用的能力.
你做不到std::invoke(f, no_move(1))
,因为这会激发转发参数的复制/移动.通过转发调用将prvalue用作参数是不可能的invoke
.您可以将prvalue传递给转发调用,但最终调用给定函数将获得xvalue.
这是避免在函数中使用固定类型作为值参数的一个很好的理由.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...>;
Run Code Online (Sandbox Code Playgroud)
这样,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
应该更复杂,并且对于指向成员的指针等“做正确的事情”。但这至少是一个简单的近似值,表明了这种方法的可行性。