【问题标题】:C++ selective predefined functor initializaiton [duplicate]C++ 选择性预定义仿函数初始化 [重复]
【发布时间】:2023-02-25 17:41:10
【问题描述】:

预定义仿函数需要就地实例化(带空括号)以用于算法,但不能用作容器适配器(如 priority_queue)的类型参数。为什么不同?

#include <queue>
#include <vector>
#include <numeric>

int main(){

   std::priority_queue<int, std::vector<int>,
   // parentheses are NOT needed here: std::greater<>
                                            std::greater<>> pq;
   pq.push(1);
   pq.push(2);
   pq.push(3);

   std::vector<int> v = {1, 2, 3};

   auto result = accumulate(v.begin(), v.end(), 0,
                              // parentheses are needed here std::plus<>()
                                                  std::plus<>());
}

【问题讨论】:

  • 因为模板形参表找的是类型,而函数形参表找的是对象。与您不写 std::max(7, int) 的原因相同。

标签: c++ templates stl functor


【解决方案1】:

std::priority_queue 是一个带有类型模板参数的类模板。它的特化要求指定类型模板参数。 std::greater&lt;&gt; 是用作类型模板参数的类型。

另一方面,在算法中,您需要提供一个功能对象,例如std::greater&lt;&gt;()

【讨论】:

    【解决方案2】:

    在这两种情况下,可调用对象的类型都是模板参数。对于 std::priority_queue,您明确声明了模板参数,一种类型。使用 std::accumulate 传递比较器的实例,以便模板参数(可以推断出比较器的类型)。

    使用 CTAD(类模板参数推导),这种差异不太明显。如果你愿意,你可以反过来说:

    #include <numeric>
    #include <queue>
    
    int main() {
        std::priority_queue pq(std::greater<int>{},std::vector<int>{});
        
        std::vector<int> x;
        std::accumulate<std::vector<int>::iterator,int,std::greater<>>(x.begin(),x.end(),0,{});
    }
    

    在这里,我利用 CTAD 让构造函数推导出传递给构造函数的参数的类型。然后使用 std::accumulate,这并不常见,但如果您愿意,可以为算法显式指定模板参数。虽然你仍然需要传递一个默认构造的实例,因为没有默认的二进制操作的重载(可能有,它只是没有那么有用,因为通常你只想写 std::accumulate(..) 并且所有模板参数都是推导)。

    【讨论】:

    • 哦,这个例子是有道理的。虽然头很痛
    猜你喜欢
    • 2013-03-01
    • 2014-03-21
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    相关资源
    最近更新 更多