三行代码  ›  专栏  ›  技术社区  ›  sovesti

参数较少的模板函数中的演绎

  •  1
  • sovesti  · 技术社区  · 1 月前

    我有几个模板函数的实例。它们中的每一个都顺序地执行每个给定的lambda,并附带特定的消息。当我使用一个lambda时,一切都很好,但是当我尝试添加多个lambda时,我得到

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

    从…起 叮当声 . 这是我的代码:

    
    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; 
    }
    

    怎么了?我该如何处理我的问题?

    抱歉,如果这是一个愚蠢的问题,我是C++的初学者,可能不理解一些模板的细微差别。

    2 回复  |  直到 1 月前
        1
  •  3
  •   JeJo    1 月前

    尽管两个传递的lambda做的相同或看起来相似,但它们的类型完全不同。因此,在中需要两种不同的模板类型 doTasks .

    Easy fix为两个lambda提供模板参数

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

    否则,使用可变模板函数和 fold expression ,您可以执行以下操作:

    #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(), ...);
        }
    }
    

    由于参数是可变的,因此它也适用于 点任务 因此没有代码重复。

    Live demo

        2
  •  1
  •   Ted Lyngmo MaHuJa    1 月前

    Lambda有不同的类型。您需要为第二个添加另一个模板参数:

    #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();
        }
    }
    

    注意:由于它是C++17,您还可以使用 constexpr if 处理 if 仅在编译时。

    Demo