简体   繁体   English

带有少量参数的模板函数的推导

[英]Deduction in template functions with few args

I have few instances of one template function.我很少有一个模板函数的实例。 Each of them sequentially executes each of given lambdas, accompanying them with specific messages.它们中的每一个都按顺序执行每个给定的 lambda,并伴随着特定的消息。 When I do that with one lambda, everything works fine, but when I try to add more than one, I get当我使用一个 lambda 执行此操作时,一切正常,但是当我尝试添加多个时,我得到

note: candidate template ignored: deduced conflicting types for parameter 'Task'

From clang .铿锵 Here is my code:这是我的代码:


template <class Task> void doTasks(Task task1)  // works fine
{  
    if (std::__is_invocable<Task>::value) 
    {
        std::cout << "doing first task" << endl;
        task1;
    }
}

template <class Task>
void doTasks(Task task1, Task task2) // deduced conflicting types
{ 
    if (std::__is_invocable<Task>::value) 
    {
        std::cout << "doing first task" << endl;
        task1();
        std::cout << "doing second task" << endl;
        task2();
    }
}


int main()
{
    doTasks([&] (){std::cout << "1" << endl;}); 

    doTasks([&] (){std::cout << "1" << endl;},
            [&] (){std::cout << "2" << endl;}); 
  
    return 0; 
}

What's wrong with it?它出什么问题了? How can I deal with my problem?我该如何处理我的问题?

Sorry if it's a stupid question, I'm some kind of beginner in C++ and may not understand some template nuances.对不起,如果这是一个愚蠢的问题,我是 C++ 的初学者,可能不理解一些模板的细微差别。

Even though the two passed lambdas does the same or looks similar, they have completely different types.尽管两个传递的 lambda 做相同或看起来相似,但它们具有完全不同的类型。 Hence, you need two different template types there in the doTasks .因此,您需要在doTasks中有两种不同的模板类型。

Easy fix is providing the template parameter for two lambdas简单的解决方法是为两个 lambdas 提供模板参数

template <class T1, class T2>
void doTasks(T1 task1, T2 task2)
{
  // ...
}

otherwise, using the variadic template function and fold expression , you could do something like:否则,使用可变参数模板函数和折叠表达式,您可以执行以下操作:

#include <type_traits> // std::conjunction_v, std::is_invocable

template <class... Ts>
void doTasks(Ts&&... lmds) {
    if (std::conjunction_v<std::is_invocable<Ts>...>) // maybe if constexpr
    {
        (lmds(), ...);
    }
}

Since the argument is variadic, it will also work for the single/ any arguments of doTasks and hence no code duplication.由于参数是可变参数,它也适用于doTasks的单个/任何参数,因此没有代码重复。

Live demo现场演示

The lambdas are of different types. lambda 有不同的类型。 You need to add another template parameter for the second one:您需要为第二个添加另一个模板参数:

#include <type_traits> // for the proper `std::invocable`

template <class Task, class AnotherTask>
void doTasks(Task task1, AnotherTask task2) {
    if constexpr (std::is_invocable_v<Task> && std::is_invocable_v<AnotherTask>) {
        std::cout << "doing first task\n";
        task1();
        std::cout << "doing second task\n";
        task2();
    }
}

Note: Since it's C++17, you can also use constexpr if to deal with the if at compile time only.注意:由于它是 C++17,因此您也可以使用constexpr if仅在编译时处理if

Demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM