使用 lambda 作为参数时无法转换模板

Cannot convert template when using lambda as parameter

我想将 lambda 传递给一个函数,但我 运行 遇到了将其成功传递给函数的问题。该函数选择附加 TrueValFalseVal 并根据给定的 condition.

创建一个布尔向量

我正在使用 2019 Visual Studio 的 ISO C++14 标准来编译代码。

#include <iostream>
#include <vector>

using namespace std;

template<typename T, typename T1, typename T2>
vector<bool> ConstructNestedVectorByElements(T condition, T1 TrueVal, T2 FalseVal) {
    vector<bool> TempCol;
        TempCol = {};
        for (int i = 0; i < 3; i++)
        {
            if (condition(i)) {
                TempCol.emplace_back(TrueVal);
            }
            else {
                TempCol.emplace_back(FalseVal);
            }
        }
    return TempCol;
}

int main()
{
    vector<int> NumList = { 0, 1, 2 };
    vector<bool> BoolList = {true, false, true};

    auto ElementIsZero = [&NumList](int i) {return NumList[i] == 0; };
    vector<bool> a = ConstructNestedVectorByElements(ElementIsZero, true, false); //this works

    auto OriginalElement = [&BoolList](int i) {return BoolList[i]; };
    vector<bool> b = ConstructNestedVectorByElements(ElementIsZero, true, OriginalElement); //error

    return 0;
};

错误信息:

C2440 'initializing': cannot convert from 'T2' to 'bool' ...\include\vector line 2385

1>...\vector(2385,18): error C2440: 'initializing': cannot convert from 'T2' to 'bool'
1>        with
1>        [
1>            T2=main::<lambda_e116e485fb739b952327b9205614af81>
1>        ]
1>...\vector(2385,18): message : No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>...\Source.cpp(19): message : see reference to function template instantiation 'decltype(auto) std::vector<bool,std::allocator<bool>>::emplace_back<T2&>(T2 &)' being compiled
1>        with
1>        [
1>            T2=main::<lambda_e116e485fb739b952327b9205614af81>
1>        ]
1>...\Source.cpp(36): message : see reference to function template instantiation 'std::vector<std::vector<bool,std::allocator<bool>>,std::allocator<std::vector<bool,std::allocator<bool>>>> ConstructNestedVectorByElements<main::<lambda_52b07f243bfcbbd5a342ddead4700eca>,bool,main::<lambda_e116e485fb739b952327b9205614af81>>(T,T1,T2)' being compiled
1>        with
1>        [
1>            T=main::<lambda_52b07f243bfcbbd5a342ddead4700eca>,
1>            T1=bool,
1>            T2=main::<lambda_e116e485fb739b952327b9205614af81>
1>        ]
template <class... _Valty>
    decltype(auto) emplace_back(_Valty&&... _Val) {
        bool _Tmp(_STD forward<_Valty>(_Val)...);
        push_back(_Tmp);

我认为问题可能是以下之一:

TempCol.emplace_back(FalseVal(i, j)); //this is line 19

出现此错误:

C2064 term does not evaluate to a function taking 2 arguments ...\Source.cpp line 19

然而,condition(i, j) 似乎并非如此,它编译正确。在有条件的情况下和将其附加到向量时,处理(我假设的)布尔值有区别吗?

问题是 OriginalElement 不是 bool,不能隐式转换为 1。您可以通过传递 int 来调用它来获得 bool。更改模板中的这一行:

TempCol.emplace_back(FalseVal(i));

然后

auto OriginalElement = [&BoolList](int i) {return BoolList[i]; };
vector<bool> b = ConstructNestedVectorByElements(ElementIsZero, true, OriginalElement);

编译正常,但传递 false 将不起作用,因为 false 不是可调用的。 T2 不能同时是可调用的和 bool。如果您希望两个实例都起作用,您可以将第一个更改为

auto ElementIsZero = [&NumList](int i) {return NumList[i] == 0; };
vector<bool> a = ConstructNestedVectorByElements(ElementIsZero, true, [](int){ return false;});

Complete Demo

不过,我建议你写两个重载。一个需要调用的。并且为了避免可调用的开销,另一个采用普通的 bool (没有模板参数,让调用者进行转换)。