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

c++std::如果……启用?

  •  3
  • Vince  · 技术社区  · 4 年前
    #include <stdio.h>
    #include <type_traits>
    
    void print()
    {
        printf("cheers from print !\n");
    }
    
    class A 
    {
      public:
      void print()
      {
          printf("cheers from A !");
      }
    };
    
    
    template<typename Function>
    typename std::enable_if< std::is_function< 
                                    typename std::remove_pointer<Function>::type >::value,
                                    void >::type 
    run(Function f)
    {
        f();
    }
    
    
    template<typename T>
    typename std::enable_if< !std::is_function< 
                                    typename std::remove_pointer<T>::type >::value,
                                    void >::type 
    run(T& t)
    {
        t.print();
    }
    
    
    
    int main()
    {
        run(print);
    
        A a;
        run(a);
    
        return 0;
    }
    

    上述代码按预期编译和打印:

    我想表达的是:“如果模板是函数,则应用此函数,否则…”。或者在另一个公式中:对于函数模板有一个函数版本,对于非函数模板有一个默认版本。

    所以,这个部分似乎有些多余,可以用“else”条件来“替换”:

    template<typename T>
    typename std::enable_if< !std::is_function< 
                                    typename std::remove_pointer<T>::type >::value,
                                    void >::type 
    run(T& t)
    

    这会存在吗?

    1 回复  |  直到 4 年前
        1
  •  6
  •   NathanOliver    4 年前

    你要找的是 constexpr if . 这样你就可以像

    template<typename Obj>
    void run(Obj o)
    {
        if constexpr (std::is_function_v<std::remove_pointer_t<Obj>>)
            o();
        else
            o.print();
    }
    

    Live Example

    如果你没有访问C++ 17但确实有C++ 14,那么你至少可以缩短你需要用Ac++编写的代码。 variable template . 看起来像是

    template<typename T>
    static constexpr bool is_function_v = std::is_function< typename std::remove_pointer<T>::type >::value;
    
    template<typename Function>
    typename std::enable_if< is_function_v<Function>, void>::type 
    run(Function f)
    {
        f();
    }
    
    
    template<typename T>
    typename std::enable_if< !is_function_v<T>, void>::type 
    run(T& t)
    {
        t.print();
    }
    

    Live Example

        2
  •  4
  •   R Sahu    4 年前

    如果你只限于使用C++ 11,你可以使用标签调度机制。

    namespace detail
    {
       template<typename Function>
       void run(std::true_type, Function& f)
       {
          f();
       }
    
       template<typename Object>
       void run(std::false_type, Object& o)
       {
          o.print();
       }
    
    } // namespace detail
    
    template<typename T>
    void run(T& t)
    {
       constexpr bool t_is_a_function = 
          std::is_function<typename std::remove_pointer<T>::type >::value;
       using tag = std::integral_constant<bool, t_is_a_function>;
       detail::run(tag{}, t);
    }
    

    Working example .