【问题标题】:How to passing function overload set as template parameter如何将函数重载集作为模板参数传递
【发布时间】:2020-04-24 20:41:10
【问题描述】:

我有这样的代码:

template<auto Function>
struct Bind
{
    template<typename... Args>
    static auto func(Args&&... args)
    {
        return std::invoke(Function, args...);
    }
};

struct F
{
    int i;
    auto foo(int ii){ i = ii; }
};

int main()
{
    F f{};
    Bind<&F::foo>::func(f, 5); //set `i` to 5
    return Bind<&F::i>::func(f); //return 5
}

但现在我需要添加新函数 int F::foo(); 并且我仍然需要能够从 func 调用这两个函数,例如:

template<typename TBind>
auto bar(F f)
{
    TBind::func(f, 5); // calls `void F::foo(int)`
    return TBind::func(f); // calls `int F::foo()`
}

是否可以在 C++17 中做到这一点并且仍然使用auto Function

(C++20 可以有自定义类型作为值模板参数来解决这个问题)

【问题讨论】:

    标签: c++ templates c++17 template-meta-programming


    【解决方案1】:

    C++17 不能将自定义对象作为模板参数传递,但允许传递指向它的指针。

    使用小的辅助函数我们可以轻松做到:

    #include <functional>
    
    //this will dereferece all arguments in form of `T*` or return it without change
    template<typename T>
    auto optDeref(T t) { return t; }
    template<typename T>
    auto optDeref(T* t) -> T& { return *t; }
    
    template<auto Function>
    struct Bind
    {
        template<typename... Args>
        static auto func(Args&&... args)
        {
            return std::invoke(optDeref(Function), std::forward<Args>(args)...);
        }
    };
    
    struct F
    {
        int i;
        void foo(int ii){ i = ii; }
        int foo() { return i; }
    };
    
    template<typename TBind>
    int bar(F f)
    {
        TBind::func(f, 5);
        return TBind::func(f);
    }
    
    struct
    {
        template<typename... Args>
        auto operator()(F& f, Args&&... args) const -> decltype(auto) { return f.foo(args...); }
    } f_overload;
    
    struct
    {
        auto operator()(F& f) const { return f.foo(); }
        auto operator()(F& f, int i) const { return f.foo(i); }
    } f_overloadLimited;
    
    int main()
    {
        F f{};
        return Bind<&F::i>::func(f) + bar<Bind<&f_overload>>(f) + bar<Bind<&f_overloadLimited>>(f);
    }
    
    
    

    工作示例:

    https://gcc.godbolt.org/z/HMuxN_(gotbolt 现在(2020-04-24)在 VS 上有一些问题,并且没有正确显示成功)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-02
      • 2012-12-27
      • 1970-01-01
      相关资源
      最近更新 更多