如何通过参数的某些质量而不是其确切类型来指定参数类型
How do I specify a parameter type by some quality of the parameter rather than its exact type?
所以我在C++中有一个函数,如下所示:
void print_vec(std::vector<int> v) {
for (int i: v) {
std::cout << i << ' ';
}
std::cout << std::endl;
}
这很有效,但只适用于int向量。我想要像一样的东西
void print_iter(Iterable<CanDoCout> iterable) {
for (auto i: iterable) {
std::cout << i << ' ';
}
std::cout << std::endl;
}
如何实现print_iter
?或者,我如何找到如何实现这样的通用函数?
您要查找的是模板:
template <class T>
void print_iter(const T& iterable) {
for (const auto& i: iterable) {
std::cout << i << ' ';
}
std::cout << std::endl;
}
您可以更进一步,使用概念或SFINAE将模板限制为仅接受您应用的操作的类型。
假设您可以访问C++20,这就是您如何使用以下概念限制模板接受的类型:
template <typename T>
concept printable = requires(T t)
{
std::cout << t;
};
template <std::ranges::range T>
requires printable<std::ranges::range_value_t<T>>
void print_iter(const T &iterable)
{
for (const auto &it : iterable)
std::cout << it << ' ';
std::cout << 'n';
}
concept printable = ...
将printable
定义为一个概念(一组(通常(类型的要求(。假设t
是T
类型的变量,当表达式std::cout << t
良好地形成时,满足这个概念。
在print_iter()
:的定义中
template <std::ranges::range T>
与template <typename T>
相同,只是它使用概念std::ranges::range
(即您所称的"可迭代"(来约束类型。requires printable<std::ranges::range_value_t<T>>
为T
添加了一个额外的约束:它要求类型std::ranges::range_value_t<T>
(T
的元素类型(满足我们的概念printable
。
如果你不想使用C++20概念(或Rust特性(,并且你仍然希望你的函数只应用于可迭代类型(因为没有人喜欢SFINAE错误(,那么一种技术是要求它有一个const_iterator:
template <typename T>
void print_range(const T& iterable, typename T::const_iterator = T{}.cbegin()) {
for (const auto& elem : iterable) {
std::cout << elem << ' ';
}
std::cout << std::endl;
}
在这种情况下,const_iterator参数必须是默认的伪参数。我之前建议使用两个迭代器,但这需要调用方明确模板类型,这并不酷。
选择const_iterator/cbegin作为可迭代(而不是一般的这种技术(的定义特征,一个公平的批评是,并非所有可迭代的东西都有这个接口。但这并不是一个真正的障碍,因为调用者可以用这个接口将其封装在一个类型中。例如,在C字符串的情况下为string_view。
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 如何解决一元"*"(有"字符")错误的无效类型参数?
- "std::shared_ptr":不是参数"_Ty"的有效模板类型参数
- 具有可变参数非类型参数的模板专用化
- 函数类型参数的模板参数推导
- PowerShell 使用结构类型参数调用 C++ DLL 的导出函数
- 对于非常量指针类型的参数,未调用具有常量指针模板类型参数的功能
- 为模板传递非类型参数 agument
- 为什么带有类型参数的运算符 () 可以应用于 result_of 上下文中的类型?
- 使用其他模板类型参数作为要在函数签名中使用的类型别名声明
- 如何避免具有相同类型参数的函数中的错误
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- c++非类型参数包扩展
- 如何实现对参数顺序不可知的std::same_as的广义形式(即对于两个以上的类型参数)
- 在不同的模板参数包之间分发非类型参数包
- 如何在使用容器和字符串时强制使用显式分配器类型参数
- 错误:一元"*"的类型参数无效(具有"int"):使用 mergesort 计算
- EXPECT_CALL具有 unique_ptr 引用类型参数的模拟函数
- 作为模板类型参数,为什么 type[N] 与其专用版本不匹配----模板<类 T>类 S<T[]>
- C++ 模板:重载时找不到基类类型参数方法