【问题标题】:C++ overloading template on assigning value or callback function赋值或回调函数的 C++ 重载模板
【发布时间】:2019-11-19 05:38:11
【问题描述】:

尝试做类似...的事情

template <class T>
struct Wrapper
{
    template <class U>
    void set(const U& u) { myT = u; }

    template <class F>
    void set(F f) { myT = f(); }

    T myT;
};

我知道我需要在这里使用 SFINAE,但是如何区分回调参数和值参数?可以安全地假设一个值不能用作回调。

我尝试过 enable_ifis_function, result_ofinvoke_resultis_invocable 等,但没有一个能正常工作。甚至可能吗?

【问题讨论】:

    标签: c++ templates c++17


    【解决方案1】:

    您可以在没有 SFINAE 的情况下做到这一点:

    template<class U>
    void set(const U& u) { 
        if constexpr (std::is_invocable_v<U>)
            myT = u();
        else
            myT = u;
    }
    

    或更通用的方式:

    template<class U>
    void set(U&& u) { 
        if constexpr (std::is_invocable_v<U>)
            myT = std::forward<U>(u)();
        else
            myT = std::forward<U>(u);
    }
    

    【讨论】:

    • 更喜欢 constexpr 而不是 SFINAE,因为编译时间更短
    【解决方案2】:

    是的,您可以在 std::is_invocable 的帮助下申请 SFINAE(自 C++17 起)。

    template <class U>
    std::enable_if_t<!std::is_invocable_v<U>> set(const U& u) { myT = u; }
    
    template <class F>
    std::enable_if_t<std::is_invocable_v<F>> set(F f) { myT = f(); }
    

    LIVE

    【讨论】:

      【解决方案3】:

      将函数作为参数的重载可以定义为:

      template <typename R>
         void set(R (*f)())
         {
            myT = f();
         }
      

      演示代码:

      #include <iostream>
      
      template <class T>
      struct Wrapper
      {
         template <class U>
            void set(const U& u)
            {
               std::cout << "In set(const U& u)\n";
               myT = u;
            }
      
         template <typename R>
            void set(R (*f)())
            {
               std::cout << "In set(R (*f)())\n";
               myT = f();
            }
      
         T myT;
      };
      
      short foo()
      {
         return 2u;
      }
      
      int main()
      {
         Wrapper<int> a;
         a.set(1u);
         a.set(foo);
      }
      

      输出:

      In set(const U& u)
      In set(R (*f)())
      

      【讨论】:

      • 这是一个糟糕的解决方案。您只接受函数指针。您不能传递 lambdas 或“可调用类”。
      猜你喜欢
      • 1970-01-01
      • 2014-07-06
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      相关资源
      最近更新 更多