其他分享
首页 > 其他分享> > c – 将std :: invoke_result_t与通用lambda一起使用时出现硬错误

c – 将std :: invoke_result_t与通用lambda一起使用时出现硬错误

作者:互联网

我有一个类似容器的类,其方法与std :: apply类似.我想用const限定符重载此方法,但是当我尝试使用泛型lambda调用此方法时,我从std :: invoke_result_t的实例化中得到了一个硬错误.我正在使用std :: invoke_result_t来推断方法的返回值以及对参数执行SFINAE检查.

#include <type_traits>
#include <utility>

template <typename T>
class Container
{
public:
    template <typename F>
    std::invoke_result_t<F, T &> apply(F &&f)
    {
        T dummyValue;
        return std::forward<F>(f)(dummyValue);
    }

    template <typename F>
    std::invoke_result_t<F, const T &> apply(F &&f) const
    {
        const T dummyValue;
        return std::forward<F>(f)(dummyValue);
    }
};

int main()
{
    Container<int> c;
    c.apply([](auto &&value) {
        ++value;
    });
    return 0;
}

使用Clang 6.0编译时出现错误消息:

main.cc:27:9: error: cannot assign to variable 'value' with const-qualified type 'const int &&'
        ++value;
        ^ ~~~~~
type_traits:2428:7: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<const int &>' requested here
      std::declval<_Fn>()(std::declval<_Args>()...)
      ^
type_traits:2439:24: note: while substituting deduced template arguments into function template '_S_test' [with _Fn = (lambda at main.cc:26:13), _Args = (no value)]
      typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type;
                       ^
type_traits:2445:14: note: in instantiation of template class 'std::__result_of_impl<false, false, (lambda at main.cc:26:13), const int &>' requested here
    : public __result_of_impl<
             ^
type_traits:2831:14: note: in instantiation of template class 'std::__invoke_result<(lambda at main.cc:26:13), const int &>' requested here
    : public __invoke_result<_Functor, _ArgTypes...>
             ^
type_traits:2836:5: note: in instantiation of template class 'std::invoke_result<(lambda at main.cc:26:13), const int &>' requested here
    using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
    ^
main.cc:16:10: note: in instantiation of template type alias 'invoke_result_t' requested here
    std::invoke_result_t<F, const T &> apply(F &&f) const
         ^
main.cc:26:7: note: while substituting deduced template arguments into function template 'apply' [with F = (lambda at main.cc:26:13)]
    c.apply([](auto &&value) {
      ^
main.cc:26:23: note: variable 'value' declared const here
    c.apply([](auto &&value) {
               ~~~~~~~^~~~~

我不确定std :: invoke_result_t是否对SFINAE友好,但我不认为这是问题,因为我尝试用尾随返回类型替换它,例如:

auto apply(F &&f) const -> decltype(std::declval<F>()(std::declval<const T &>()))

并得到一个类似的错误:

main.cc:27:9: error: cannot assign to variable 'value' with const-qualified type 'const int &&'
        ++value;
        ^ ~~~~~
main.cc:16:41: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<const int &>' requested here
    auto apply(F &&f) const -> decltype(std::declval<F>()(std::declval<const T &>()))
                                        ^
main.cc:26:7: note: while substituting deduced template arguments into function template 'apply' [with F = (lambda at main.cc:26:13)]
    c.apply([](auto &&value) {
      ^
main.cc:26:23: note: variable 'value' declared const here
    c.apply([](auto &&value) {
               ~~~~~~~^~~~~

问题:

>为什么会这样?更准确地说,为什么lambda的身体在过度解决期间被实例化,似乎是什么?
>我该如何解决?

解决方法:

除非您明确指定返回类型,否则Lambdas已推导出返回类型.因此,std :: invoke_result_t必须实例化主体才能确定返回类型.此实例化不在紧邻的上下文中,并导致硬错误.

您可以通过编写代码来编译代码:

[](auto &&value) -> void { /* ... */ }

在这里,lambda的主体将不会被实例化,直到申请的身体,你是明确的.

标签:c,sfinae,c17,generic-lambda
来源: https://codeday.me/bug/20190724/1521065.html