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

如何解决这种多变的模板歧义

  •  1
  • Janilson  · 技术社区  · 2 年前

    只要 someFuncTemplate(func1) 已被注释掉。但是,一旦取消注释,编译就会失败,并出现错误“value”不是“Arity<int(*)(int,int)>”编译错误,我认为这是由于编译器在 Arity<F>::value 。我尝试从第一个模板中删除括号,但问题仍然存在,只是这次出现了“不完整类型”编译错误。

    使用时如何强制编译器选择正确的模板 Arity<F> ?

    #include <iostream>
    
    template <typename T>
    struct Arity {};
    
    template <typename Ret, typename... Args>
    struct Arity<Ret(Args...)>
        : std::integral_constant<size_t, sizeof...(Args)> 
    {};
    
    int func1(int a, int b) { return a + b; }
    
    template <typename F>
    void someFuncTemplate(F)
    {
        std::cout << Arity<F>::value;
    }
    
    int main()
    {
        std::cout << Arity<decltype(func1)>::value << '\n';
        //someFuncTemplate(func1);
    }
    
    2 回复  |  直到 2 年前
        1
  •  4
  •   Ted Lyngmo    2 年前

    您需要为第二种情况添加另一个专业化:

    template <typename Ret, typename... Args>
    struct Arity<Ret (*)(Args...)> : Arity<Ret(Args...)> {};
    //               ^^^
    

    您也可以添加

    template <typename Ret, typename... Args>
    struct Arity<Ret (&)(Args...)> : Arity<Ret(Args...)> {};
    

    以便进行如下函数声明:

    template <typename F>
    void someFuncTemplate(F&&) {
        std::cout << Arity<F>::value;
    }
    

    Demo

        2
  •  2
  •   Jerry Coffin    2 年前

    作为为指向函数的指针添加专门化的替代方案,您可以修改 someFunctTemplate 引用其论点:

    // preceding unchanged
    
    template <typename F>
    void someFuncTemplate(F const &)
    //......................^^^^^^^
    {
        std::cout << Arity<F>::value;
    }
    
    int main()
    {
        someFuncTemplate(func1);
    }