使用函数模板参数作为类模板参数?

时间:2018-05-20 12:17:55

标签: c++ templates

我试图通过实现类似于C#的Linq来熟悉C ++中的模板。最后,查询数据看起来应该是这样的

SomeIteratorType begin = /* ... */;
SomeIteratorType end = /* ... */;
typedef iterator_traits<SomeIteratorType>::value_type Type;

linq<int> query = linq<Type>(begin, end)
                  .where([](Type value) -> bool { return /* ... */; })
                  .select([](Type value) -> int { return value.some_property; });

for (int value : query)
    cout << value << endl;

我从

开始
template<typename Type>
class linq : public std::iterator<std::input_iterator_tag, Type> {
public:
    typedef bool (WherePredicate)(Type value);

    // ...
    // Copy-constructor, operator=, operator++, ...
    // ...

    // ...
    // Linq functions, e.g.
    linq& where (WherePredicate& predicate) const; // returns some specialization of the linq-class (should probably not name this "where")
    // ...
};

但是如何从示例中声明构造函数linq(begin, end)?如果beginend属于IteratorType类型,我需要生成的linq对象属于linq<std::iterator_traits<IteratorType>::value_type>类型。甚至可以从函数模板参数中计算出类模板参数吗?如果没有,是否至少可以确保IteratorType beginIteratorType end足够std::iterator_traits<IteratorType>::value_type == Type,就像linq<Type>(begin, end)一样使用?

1 个答案:

答案 0 :(得分:0)

因此C#使用堆分配的对象和间接通过接口,就好像它是免费的一样。

如果你想模仿它,你必须这样做。如果你也想要值语义,你必须编写包含智能指针的包装器,并且表现得像值。

另一种方法是不输入擦除;相反,linq对象是每个修饰符链的唯一类型。这里linq是一个函数而不是tyoe,并且您将返回值存储在auto个变量中。

这两种方法可以一起工作,比如lambda(没有类型ersaure callables)和std函数(可以在构造时堆积分配和类型擦除的值类型,以便忘记除callable之外的所有调用接口)。

为了更进一步,了解类型擦除(包括如何编写std函数),使用C ++中的常规类型,并且可以在Rangesv3中查找一个支持类似linq的流表达式的库。