如何通过两个lambda函数的返回类型来区分它们?

时间:2019-09-29 02:22:52

标签: c++ lambda operator-overloading c++17

我正在尝试为lambda函数创建类似bash的管道运算符重载,其中您将矢量传递给lambda,该lambda可以过滤或打印矢量

我尝试将auto与decltype一起使用,尝试将它们全部放在同一个函数中,希望auto知道何时返回void和何时返回向量,但我尝试执行的所有操作都不编译或说出模棱两可的重载。 / p>

这是代码,

#include <iostream>
#include <algorithm>
#include <functional>
#include <type_traits>

using namespace std;

void operator | ( auto& v, auto map ) {
  for( auto x : v )
    map( x );
}

template <typename T>
T operator | ( T& vet, auto map)  {
    cout << "else" << endl;
    T aux;
    for ( auto x : vet) 
        aux.push_back(x);
    return aux;
}

int main () {
    vector<int> v{1,2,3,4,5,6,7,8} ;
     v | []( int x ) { return x % 2 == 0; } | [] ( int x ) { cout << x << endl; };
     v | [] ( int x ) { cout << x << endl; };
    return 0;
}

会发生什么:

trabapply3.cc:25:6: error: ambiguous overload for ‘operator|’ (operand types are ‘std::vector<int>’ and ‘main()::<lambda(int)>’)
   25 |    v | [] ( int x ) { cout << x << endl; };

有什么提示吗?

1 个答案:

答案 0 :(得分:1)

使用std::is_invocable_r / std::invoke_result_t

#include <iostream>
#include <algorithm>
#include <functional>
#include <type_traits>
#include <vector>

template<typename T>
using element_type_t = std::remove_reference_t<decltype(*std::begin(std::declval<T&>()))>;

template <typename T, typename MapFunc, std::enable_if_t<std::is_void_v<std::invoke_result_t<MapFunc, element_type_t<T>>>, std::nullptr_t> = nullptr>
void operator | (const T& v, MapFunc&& map ) {
  for(auto&& x : v )
    map( x );
}

template <typename T, typename MapFunc, std::enable_if_t<std::is_invocable_r_v<element_type_t<T>, MapFunc, element_type_t<T>>, std::nullptr_t> = nullptr>
T operator | (const T& vet, MapFunc&& map)  {
    T aux;
    for (auto&& x : vet) 
        aux.push_back(map(x));
    return aux;
}

int main () {
    std::vector<int> v{1,2,3,4,5,6,7,8} ;
     v | []( int x ) { return x % 2 == 0; } | [] ( int x ) { std::cout << x << std::endl; };
     v | []( int x ) { std::cout << x << std::endl; };
    return 0;
}

https://wandbox.org/permlink/33zSMBubghwEt4EF

注意:关于element_type_t:观看Type trait to get element type of std::array or C-style array

顺便说一句,您不应该写using namespace std;