15

中,我们有花哨的is_invocable新纯右值和花哨的新纯右值,它们并不是真正的值。

这允许您创建一个对象,而不必先从逻辑上构造它,然后省略构造。

我遇到了一个问题,使用std::is_invocable来测试你是否可以调用某些东西,并且prvalue规则似乎发生冲突:

struct no_move {
  no_move(no_move&&)=delete;
  explicit no_move(int) {}
};
void f( no_move ) {}

现在我们可以问是否f可以使用类型的纯右值调用no_move

f( no_move(1) )

std::is_invocable< decltype(&f), no_move >不起作用,因为它使用std::declval<no_move>()which is an x​​value like no_move&&not a prvalue of type no_move

中这是相同的,但保证省略使一些函数可以用 xvalue(即“ T&&”)调用,而另一些函数可以用 prvalues 类型调用T

是否有替代方案,或者我们必须发明自己的特征来处理这种情况?

(在一个std::declval<T>返回T而不是 ,T&&的理论世界中is_invocable,我相信会做正确的事情)。

4

2 回答 2

6

您在滥用 Invocable 概念。这个概念仅意味着std::invoke在给定函数和提供的参数上使用的能力。

你不能这样做std::invoke(f, no_move(1)),因为这会引发转发参数的复制/移动。prvalue 不可能通过转发调用(如invoke. 您可以将纯右值传递给转发调用,但对给定函数的最终调用将获得一个 xvalue。

这是避免在函数中使用固定类型作为值参数的一个很好的理由。带他们const&过去。

C++ 没有类型特征来查看是否可以以您想要的方式使用特定参数调用函数。

于 2018-01-09T19:25:44.863 回答
3

是否有替代方案,或者我们必须发明自己的特征来处理这种情况?

是的,您只需要编写自己的不使用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应该更复杂,并且为指向成员的指针等“做正确的事”。但这至少是一个简单的近似值,表明这种方法的可行性。

于 2018-01-09T19:46:22.783 回答