代码之家  ›  专栏  ›  技术社区  ›  Dr.Knowitall

如何用特定的签名构建函数概念?

  •  2
  • Dr.Knowitall  · 技术社区  · 7 年前

    我正在使用概念编写一些通用软件,我想检查结构上是否存在签名为(void)(int,int)的特定函数符号名称。为了做到这一点,我正在考虑通过模板专门化来解决这个问题,但我有点迷路了。

    我想要的是一些有用的东西,如果这个概念不能像这样得到满足,那么通过编译时错误:

    struct TypeA {
      // Passes concept
      void process (int a ,int b) const {};
    };
    
    struct TypeB {
      // Does not pass concept
      void process (float a) const {};
    };
    
    struct TestConcepts {
      /* concept code here */
      TestConcepts(T t) {
        process_concept(t.process);
      };
    };
    
    int main(void) {
      // Should pass
      TestConcept(TypeA{});
      // Should throw error
      TestConcept(TypeB{});
      return 0;
    }
    

    我很难填补空白,但这就是我目前为止所拥有的:

    struct TestConcepts {
          /* concept code here */
          struct process_concept {
            process_concept((V*)(IA,IB)){
                if (is_integral<IA>::value && is_integral<IB>::value && is_same<V, void>) {
                    return;
                }
                static_assert(false, "You must provide function called process of type (void)(int,int)");
            };
        };
          TestConcepts(T t) {
            process_concept(&t.process);
          };
        };
    

    不幸的是,这行不通。如何正确获取此函数签名?

    1 回复  |  直到 7 年前
        1
  •  2
  •   JHBonarius    7 年前

    struct TypeA {
        // Passes concept
        void process (int a ,int b) const {};
    };
    
    struct TypeB {
        // Does not pass concept
        void process (float a) const {};
    };
    
    template<typename T>
    auto TestConcepts(T) -> void(T::*)(int, int) const
    {
        return &T::process;
    }
    
    int main(void) {
        // Should pass
        TestConcepts(TypeA{});
        // Should throw error
        TestConcepts(TypeB{});
        return 0;
    }
    

    Error(s):
    
    source_file.cpp: In instantiation of ‘void (T::* TestConcepts(T))(int, int) const [with T = TypeB]’:
    source_file.cpp:26:23:   required from here
    source_file.cpp:19:16: error: cannot convert ‘void (TypeB::*)(float) const’ to ‘void (TypeB::*)(int, int) const’ in return
         return &T::process;
                    ^
    

    void process(long int a, long int b) const; void process(int a, int b, int c=0) const;

    struct TypeA {
        // Passes concept
        void process(int a, int b) const {};
    };
    
    struct TypeB {
        // Does not pass concept
        void process(float a) const {};
    };
    
    struct TypeC {
        // Passes concept
        void process(long int a, long int b) const {};
    };
    
    struct TypeD {
        // Passes concept
        void process(int a, int b, int c = 0) const {};
    };
    
    struct TypeE {
        // Does not pass concept
        void process(int a, int b, int c) const {};
    };
    
    #include <type_traits>
    template<typename T, typename A1, typename A2, typename... An>
    typename std::enable_if<
        std::is_integral<A1>::value &&
        std::is_integral<A2>::value
    >::type
    TestProcess(const T& t, void(T::*)(A1, A2, An...) const) {
        t.process(1, 2);
    };
    
    template<typename T>
    void TestConcepts(const T& t)
    {
        TestProcess(t, &T::process);
    }
    
    int main(void) {
        // Passes
        TestConcepts(TypeA{});
        // Throws compilation error
        TestConcepts(TypeB{});
        // Passes
        TestConcepts(TypeC{});
        // Passes
        TestConcepts(TypeD{});
        // Throws compilation error
        TestConcepts(TypeE{});
    
        return 0;
    }