Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 基于lambda参数重载函数模板_C++_Templates_Overloading - Fatal编程技术网

C++ 基于lambda参数重载函数模板

C++ 基于lambda参数重载函数模板,c++,templates,overloading,C++,Templates,Overloading,我正在尝试创建一个函数,在该函数中,调用者可以通过一组特定的已知参数传入lambda(返回类型可以是调用者想要的任何类型) 假设可能的lambda签名是 T(小部件*) T(Widget2*) 我试过几件事,但都没能成功 struct Widget2{ int count = 0; }; class Widget { public: template<typename Fn, typename T = std::invoke_result_t<Fn, Widget*>

我正在尝试创建一个函数,在该函数中,调用者可以通过一组特定的已知参数传入lambda(返回类型可以是调用者想要的任何类型) 假设可能的lambda签名是

  • T(小部件*)
  • T(Widget2*)
  • 我试过几件事,但都没能成功

    struct Widget2{
        int count = 0;
    };
    
    class Widget {
    public:
    template<typename Fn, typename T = std::invoke_result_t<Fn, Widget*>>
    T doIt(Fn&& fn)
    {
        return fn(_sibling);
    }
    
    template<typename Fn, typename T = std::invoke_result_t<Fn, Widget2*>>
    T doIt(Fn&& fn)
    {
        return fn(_other);
    }
    
    private: 
    Widget* _sibling = nullptr;
    Widget2* _other = nullptr;
    };
    
    struct Widget2{
    整数计数=0;
    };
    类小部件{
    公众:
    模板
    T doIt(Fn和&Fn)
    {
    返回fn(_同胞);
    }
    模板
    T doIt(Fn和&Fn)
    {
    返回fn(_其他);
    }
    私人:
    Widget*_sibling=nullptr;
    Widget2*_other=nullptr;
    };
    
    我也试过这样做

    template<typename Fn>
    auto doIt(Fn&& fn)
    {
        if (std::is_invocable_v<Fn, Widget*>)
            return fn(_sibling);
        else if (std::is_invocable_v<Fn, Widget2*>)
            return fn(_other);
    }
    
    模板
    自动doIt(Fn&&Fn)
    {
    如果(标准::是否可发票)
    返回fn(_同胞);
    否则如果(标准::是否可发票)
    返回fn(_其他);
    }
    
    编译器中的以下代码:

    我宁愿避免添加多个函数,比如doItWidget1、doItWidget2等等


    有没有一种方法可以基本上根据传入lambda的参数重载函数?

    如果可以使用
    enable\u来消除错误的重载

    template<typename Fn, std::enable_if_t<std::is_invocable_v<Fn, Widget*>, int> = 0>
    auto doIt(Fn&& fn)
    {
        return fn(_sibling);
    }
    
    template<typename Fn, std::enable_if_t<std::is_invocable_v<Fn, Widget2*>, int> = 0>
    auto doIt(Fn&& fn)
    {
        return fn(_other);
    }
    
    模板
    自动doIt(Fn&&Fn)
    {
    返回fn(_同胞);
    }
    模板
    自动doIt(Fn&&Fn)
    {
    返回fn(_其他);
    }
    
    请注意,您甚至不需要计算返回类型
    t
    ,只需使用
    auto
    即可


    这里有一个。

    Simpler:
    template std::invoke\u result\t>doIt(Fn&&Fn)
    ,它也会触发SFINAE,但更简单,不可绕过。或者
    template auto doIt(Fn&&Fn)->decltype(Fn(_sibling)){return Fn(_sibling);}
    ,或者
    template auto doIt(Fn&&Fn){return Fn(_sibling);}
    ,具体取决于您的编译器版本这是完美的。如果我在模板中显式指定了类型,我希望编译器能够找出它。我很好奇为什么
    template T doIt(Fn&&Fn)
    失败了,但是用相同的值替换T是有效的
    std::invoke\u result\T doIt(…)
    有效的。