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

检查函数模板的所有参数包参数是否属于int

  •  1
  • rookie  · 技术社区  · 1 年前

    我希望我的函数接受类型为的可变参数 int 只有例如,要计算sum(取自C++核心指南):

    template<class ...Args>
    auto sum(Args... args) // GOOD, and much more flexible
    {
        return (... + args); // note: C++17 "fold expression"
    }
    
    

    以中的这个简单示例为例 std::conjunction -

    template<typename T, typename... Ts>
    std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>, int>
    control(T, Ts...)
    {
        std::cout << "all types in pack are T\n";
        return 0;
    }
    

    似乎检查了类型T和Ts,这不是我想要的(如果所有类型的args都说 double )。

    我该怎么做?

    其次,连词示例拆分T和Ts只是为了检查类型吗?它的预期用途只是一组可变参数?这种模式叫什么?

    2 回复  |  直到 1 年前
        1
  •  1
  •   Jan Schultke    1 年前

    如果您想要一个只接受变量 int s、 中的折叠表达式 std::enable_if 可以做到:

    template<class ...Args>
    auto sum(Args... args)
        -> std::enable_if_t<(... && std::is_same_v<Args, int>), int>
    // note: It's best to use std::enable_if_t in return types.
    //       The actual return type is int here, std::enable_if_t is just wrapping it
    //       for the sake of doing SFINAE.
    {
        // note: use zero to get a value for empty packs
        return (0 + ... + args);
    }
    

    使用 std::conjunction 在这里有些过头了,尤其是因为fold表达式在C++17中也能很好地完成任务。是的,把包分成 T Ts 只是为了让我们能够比较 Ts公司 到第一种类型通过 std::is_same_v<T, Ts>...

    然而,这是 真正地 令人质疑的设计,因为:

    • 这将实例化单独的函数 sum<int> , sum<int, int> 。。。(不利于编译性能)
    • 我们不能用类型为的参数调用此函数 long float ,因为即使它们是常数,替换也会失败,并且我们知道转换为 整数 是安全的

    A. 更理智的设计是使用 std::initializer_list<int> 以下为:

    #include <numeric>
    
    int sum(std::initializer_list<int> args)
    {
        return std::reduce(args.begin(), args.end());
    }
    
    // call with sum({1, 2, 3, 4})
    

    是的,这将需要我们使用额外的大括号,但隐式转换有效,而且该函数甚至不再是模板,因此值得使用。

        2
  •  1
  •   NathanOliver    1 年前

    可以在中使用fold表达式 enable_if 以下为:

    template<typename... Args, 
             std::enable_if_t<(... && std::is_same_v<Args, int>), bool> = true>
    auto sum(Args... args) // GOOD, and much more flexible
    {
        return (... + args); // note: C++17 "fold expression"
    }