c++ - 如何为模板函数实现容器和迭代器的重载?

标签 c++ templates overloading

我想要一个模板函数的 4 个重载。该函数采用一系列值 y 和另一个值范围 x。这些范围可以指定为迭代器或容器。如果作为容器传递,则使用 begin 为容器调用迭代器函数/end .对于 x 存在一种特殊情况,其中传递标量 x 将被视为好像 [begin, end) 范围内的所有 x 都是该值。

#include <iterator>
#include <vector>


// 1) Take iterator [begin, end) for y values and scalar for x
template <typename Iterator>
std::vector<double>
func(Iterator ybegin, Iterator yend, typename Iterator::value_type x = 1.) {}


// 2) take sequence of y values and scalar for x
template <typename Sequence>
std::vector<typename Sequence::value_type> 
func(const Sequence& y, typename Sequence::value_type x = 1.) {
    return func(y.begin(), y.end(), x);
}


// 3) take iterator [begin, end) for y values and iterator [begin, end) for x values
template <typename Iterator1, typename Iterator2>
std::vector<double> 
func(Iterator1 ybegin, Iterator1 yend, Iterator2 xbegin, Iterator2 xend) {}


// 4) take sequence of y values and sequence of x values
template <typename Sequence1, typename Sequence2>
std::vector<double> 
func(const Sequence1& y, const Sequence2& x) {
    return func(y.begin(), y.end(), x.begin(), x.end());
}


int main() {
    std::vector<double> a{4, 5, 6};
    std::vector<int> b{1, 1, 1};
    func(a.begin(), a.end(), 0.2);
    func(a.begin(), a.end(), b.begin(), b.end());
    func(a, 0.2);
    func(a, b);
}

我在上面发布的代码无法编译,因为调用了 std::vectordouble适合功能 2)(正确)和 4)(不正确)。

error: call of overloaded ‘func(std::vector<double>&, double)’ is ambiguous
     func(a, 0.2);
                ^
scratch_1.cpp:33:44: note: candidate: ‘std::vector<typename Sequence::value_type> func(const Sequence&, typename Sequence::value_type) [with Sequence = std::vector<double>; typename Sequence::value_type = double]’
 std::vector<typename Sequence::value_type> func(const Sequence& y,
                                            ^~~~
scratch_1.cpp:50:21: note: candidate: ‘std::vector<double> func(const Sequence1&, const Sequence2&) [with Sequence1 = std::vector<double>; Sequence2 = double]’
 std::vector<double> func(const Sequence1& y, const Sequence2& x) {

如果我使用以下版本的 2) 和 4),我会得到

// 2)
template <typename Sequence>
std::vector<typename Sequence::value_type>
func(const Sequence& y, typename std::enable_if<std::is_scalar<typename Sequence::value_type>::value,
                                                typename Sequence::value_type>::type x = 1.) {
    return func(y.begin(), y.end(), x);
}

// 4)
template <typename Sequence1, typename Sequence2>
std::vector<double>
func(const Sequence1& y,
     const typename std::enable_if<!std::is_scalar<Sequence2>::value, Sequence2>::type& x) {
    return func(y.begin(), y.end(), x.begin(), x.end());
}

error: no matching function for call to ‘func(std::vector<double>&, std::vector<int>&)’因为无法推断出第二个 vector 的类型。

 error: no matching function for call to ‘func(std::vector<double>&, std::vector<int>&)’
     func(a, b);

candidate: ‘template<class Sequence1, class Sequence2> std::vector<double> func(const Sequence1&, const typename std::enable_if<(! std::is_scalar<Sequence2>::value), Sequence2>::type&)’
 std::vector<double> func(const Sequence1& y, const typename
                     ^~~~
note:   template argument deduction/substitution failed:
note:   couldn't deduce template parameter ‘Sequence2’ func(a, b);

最佳答案

使用 is_container ,这是我公然偷来的:

// 2) take sequence of y values and scalar for x
template <typename Sequence, 
        std::enable_if_t<is_container<Sequence>::value, int> =0
>
std::vector<typename Sequence::value_type> 
func(const Sequence& y, typename Sequence::value_type x = 1.) {
    return func(y.begin(), y.end(), x);
}

// 4) take sequence of y values and sequence of x values
template <typename Sequence1, typename Sequence2, 
        std::enable_if_t<is_container<Sequence1>::value, int> =0, 
        std::enable_if_t<is_container<Sequence2>::value, int> =0 
>
std::vector<double> 
func(const Sequence1& y, const Sequence2& x) {
    return func(y.begin(), y.end(), x.begin(), x.end());
}

http://coliru.stacked-crooked.com/a/90087c6a4c9b4901

关于c++ - 如何为模板函数实现容器和迭代器的重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58085520/

相关文章:

c++ - 'typename Enable = void' 是什么意思?

Java 方法重载和可变参数

list - Haskell - 如何计算嵌套列表中的元素

c++ - Visual C++ BigInt 和 SecureRandom?是否有带有 modPow 的 BigInt 库?

c++ - 元组统一初始化

python - 将矩阵乘法从 Python 转换为 C++

c++ - Lambda 作为模板变量

c++ - C++ 中的模板参数太多?

c++ - 有没有办法在非模板类中定义模板成员?

c++ - 从 'int' 到非标量类型赋值运算符的转换 - object 到 int