我想要一个模板函数的 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::vector
和 double
适合功能 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),我会得到 p>
// 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());
}
关于c++ - 如何为模板函数实现容器和迭代器的重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58085520/