代码之家  ›  专栏  ›  技术社区  ›  bradgonesurfing

如何为重载lambda技巧提供复制构造函数

  •  0
  • bradgonesurfing  · 技术社区  · 5 年前

    下面的代码扩展了 超载 使用lambda进行技巧,以同时接受变体。然而,该变体不是示例中的问题。

    https://godbolt.org/z/GxhaPr

    #include <memory>
    #include <variant>
    #include <functional>
    
    template <class ...Fs>
    struct overload : Fs... {
        template <class ...Ts>
        overload(Ts&& ...ts) : Fs{std::forward<Ts>(ts)}...
        {} 
        using Fs::operator()...;
    
        template <class ...Vs>
        auto operator()(std::variant<Vs...>&&arg){
            return std::visit(*this,std::forward<decltype(arg)>(arg));
        }
    
    };
    
    template <typename ...Ts>
    overload(Ts&&...) -> overload<std::remove_reference_t<Ts>...>;
    
    using Foo = std::variant<int, char*, double,long>;
    
    int main()
    {
        
        auto fn = overload(
                    [](int x){ return 0;}
                    ,[](char * x) {return 1;}
                    ,[](double x){ return 2;}
                    ,[](long x){ return 3;}
        );
    
        std::function<int(Foo)> fn2 = overload(
                    [&](auto x){return fn(x);}
        );
    
        //auto ff = fn;
        //std::function<int(Foo)> fn3 = fn;
    
        auto a = fn2(10);
        auto b = fn2((char *)"10");
        auto c = fn2(10.);
    
        auto d = fn(10);
        auto e = fn((char *)"10");
        auto f = fn(10.);
    
        return a+b+c+d+e+f;
    }
    

    这很好用。但如果我取消注释这行

    auto ff=fn;
    

    然后代码失败,因为 overload 不起作用。可以写一个吗?

    1 回复  |  直到 5 年前
        1
  •  1
  •   AVH    5 年前

    代码无法编译的原因不是 overload 的默认复制构造函数不起作用。这是因为模板化构造函数基本上是一个包罗万象的东西。任何构造函数参数都会匹配它,所以它总是被调用。

    你可以在桌子上用一些SFINAE 超载 构造函数,以确保不会调用它进行复制/移动构造:

    template <class ...Fs>
    struct overload : Fs... {
        template <class ...Ts, std::enable_if_t<
            (sizeof...(Ts) == sizeof...(Fs))
            and (std::is_same_v<Fs, std::remove_reference_t<Ts>> && ...)
          , int> = 0>
        overload(Ts&& ...ts) : Fs{std::forward<Ts>(ts)}...
        {} 
        
        // Rest of existing overload code goes here.
    };
    

    请注意,我不确定我使用的条件是否正确 std::enable_if 完全正确,但我认为它们在这里是有意义的。他们让你的例子编译,所以。。。

    godbolt上解决方案代码的链接: https://godbolt.org/z/Tzn9f3 .

    推荐文章