是否可以从范围参数推断出范围的值类型



如果您查看像std::ranges::fillstd::ranges::generate这样的标准算法,它们似乎都使用了额外的参数来推断其输出范围的范围值类型。例如,ranges::fill(v, 10)由于其第二个自变量而能够推导出值类型T

然而,当您试图定义一个类似的函数,但去掉了第二个参数时,C++将无法再推导出值类型。例如,考虑以下函数:

template<typename T, std::output_range<const T&> R>
void ones(R && r)
{
for (T & value : r) {
value = 1;
}
}

如果您尝试在未明确指定值类型的情况下调用该代码,则该代码将不会编译:

std::array<int, 3> a;
// ones(a);   // does not compile
ones<int>(a); // redundant!

当我试图编译注释掉的代码时,我得到了以下错误:

/home/josiest/sandbox/cpp/template-template-range/sketch.cpp: In function ‘int main()’:
/home/josiest/sandbox/cpp/template-template-range/sketch.cpp:19:9: error: no matching function for call to ‘ones(std::array<int, 3>&)’
19 |     ones(a);
|     ~~~~^~~
/home/josiest/sandbox/cpp/template-template-range/sketch.cpp:9:6: note: candidate: ‘template<class T, class R>  requires  output_range<R, T> void ones(R&&)’
9 | void ones(R && r)
|      ^~~~
/home/josiest/sandbox/cpp/template-template-range/sketch.cpp:9:6: note:   template argument deduction/substitution failed:
/home/josiest/sandbox/cpp/template-template-range/sketch.cpp:19:9: note:   couldn’t deduce template parameter ‘T’
19 |     ones(a);
|     ~~~~^~~

有没有什么方法可以推断出我缺少的范围值类型,或者这是不可能的?

听起来你想要:

template <typename T> requires std::output_range<T, std::ranges::range_value_t<T>>

或者,也许:

template <typename T> requires std::output_range<T, const std::ranges::range_value_t<T> &>

前者希望元素被移动,后者希望元素被复制。如果要同时支持这两种约束,则可以同时使用这两个约束。

最新更新