C++ std::在泛型lambda上绑定-自动类型推断

C++ std::在泛型lambda上绑定-自动类型推断,c++,c++14,C++,C++14,考虑以下代码: #include <iostream> #include <functional> int main() { auto run = [](auto&& f, auto&& arg) { f(std::forward<decltype(arg)>(arg)); }; auto foo = [](int &x) {}; int var; auto ru

考虑以下代码:

#include <iostream>
#include <functional>

int main() {
    auto run = [](auto&& f, auto&& arg) {
        f(std::forward<decltype(arg)>(arg));
    };
    auto foo = [](int &x) {};
    int var;
    auto run_foo = std::bind(run, foo, var);
    run_foo();
    return 0;
}
#包括
#包括
int main(){
自动运行=[](自动和f、自动和参数){
f(std::forward(arg));
};
自动foo=[](int&x){};
int-var;
自动运行\u foo=std::bind(运行,foo,var);
run_foo();
返回0;
}
使用clang编译时,会出现以下编译错误:

$ clang++ -std=c++14 my_test.cpp

my_test.cpp:6:9: error: no matching function for call to object of type 'const (lambda at my_test.cpp:8:16)'
        f(std::forward<decltype(arg)>(arg));
        ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../include/c++/6.3.1/functional:998:14: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<const (lambda at my_test.cpp:8:16) &, const int &>' requested here
        = decltype( std::declval<typename enable_if<(sizeof...(_Args) >= 0),
                    ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../include/c++/6.3.1/functional:1003:2: note: in instantiation of default argument for 'operator()<>' required here
        operator()(_Args&&... __args) const
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
my_test.cpp:11:12: note: while substituting deduced template arguments into function template 'operator()' [with _Args = <>, _Result = (no value)]
    run_foo();
           ^
my_test.cpp:8:16: note: candidate function not viable: 1st argument ('const int') would lose const qualifier
    auto foo = [](int &x) {};
               ^
my_test.cpp:8:16: note: conversion candidate of type 'void (*)(int &)'
1 error generated.
$clang++-std=c++14 my_test.cpp
my_test.cpp:6:9:错误:调用类型为“const(my_test.cpp:8:16时的lambda)”的对象时没有匹配函数
f(标准:正向(arg));
^
/usr/bin/./lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../../../include/c++/6.3.1/functional:998:14:注意:在函数模板专门化的实例化中,此处请求了“main():(匿名类)::operator()
=decltype(标准::declvalMWE:

在重载解析所必需的模板参数推导过程中,默认模板参数将被实例化,这会由于闭包内的错误格式赋值而导致硬错误

这可以通过一个推断的占位符来解决:完全删除
\u Result
及其默认参数,并将返回类型声明为
decltype(auto)
。这样,我们还可以消除影响重载解析的SFINAE,从而导致错误行为:

#include <functional>
#include <type_traits>

struct A {
  template <typename T>
  std::enable_if_t<std::is_const<T>{}> operator()(T&) const;
};

int main() {
    int i;
    std::bind(A{}, i)();
} 
#包括
#包括
结构A{
模板
std::enable_if_t operator()(t&)const;
};
int main(){
int i;
绑定(A{},i)();
} 

这不应该像上面解释的那样编译,传递给
A::operator()
的参数应该是非
const
,因为
i
和转发调用包装器都是。但是,这在libc++和libstdc++下编译,因为它们的
操作符()
s在非
const
版本在SFINAE下失败后,返回到
const
版本。

如果有帮助,
arg
被推断为
int
,但是因为
操作符()
const
,存储的
var
const
@raket1111如果我没有弄错的话,这里有一个不合格的
operator()
,当
这个
const
时调用
const
版本,这使得它更奇怪。在我的实现中,我只能看到
operator()常量,但是是的,这很奇怪。模板参数的推导和替换发生在重载解析之前,所以即使
操作符()const
不会通过重载解析选择,替换仍然会发生。在这种情况下,替换失败不会出现在直接上下文中,因此此替换失败是一个硬错误。@从实现的角度来看,这是一个很好的答案,但标准只说明了
run_foo()的效果
run(foo,var)
,不是吗?我看不出它在哪里说“除非调用
as_const(run)(as_const(foo),as_const(var))
是格式错误的”或类似的东西。
  // Call as const
template<typename... _Args, typename _Result
  = decltype( std::declval<typename enable_if<(sizeof...(_Args) >= 0),
           typename add_const<_Functor>::type&>::type>()(
               _Mu<_Bound_args>()( std::declval<const _Bound_args&>(),
                                   std::declval<tuple<_Args...>&>() )... ) )>
_Result operator()(_Args&&... __args) const 
#include <functional>
#include <type_traits>

struct A {
  template <typename T>
  std::enable_if_t<std::is_const<T>{}> operator()(T&) const;
};

int main() {
    int i;
    std::bind(A{}, i)();
}