使用dectlype推导出模板元素类型中的数据类型是否正确?
Is it correct to use dectlype to deduce the data type in template's element type?
你好,我被要求在这个例子中模拟算法 std::copy_if
,将奇数复制到 s list
个整数中,偶数也复制到另一个列表中,所以这是我的例子:
#include <list>
#include <vector>
#include <iostream>
template <typename T>
bool is_odd_pred(T x) {
return x % 2 != 0;
}
template <typename T>
bool is_even_pred(T x) {
return !(x % 2);
}
template <class T, class U>
void cpy_if(T first, T last, U destIt, bool(*pfnPred)(decltype(*first + 1))) {
while (first != last) {
if (pfnPred(*first))
*destIt++ = *first;
++first;
}
}
int main() {
std::vector<int> v1{ 10, 27, 57, 77, 81, 24, 16, 23, 28 };
for (auto i : v1)
std::cout << i << ", ";
std::cout << std::endl;
std::list<int> li_odd;
//cpy_if(v1.cbegin(), v1.cend(), li.begin(),
// [](decltype(*v1.cbegin() + 1) a) { return (a % 2 != 0); });
cpy_if(v1.cbegin(), v1.cend(), std::back_inserter(li_odd), is_odd_pred);
for (auto i : li_odd)
std::cout << i << ", ";
std::cout << std::endl;
std::list<int> li_even;
cpy_if(v1.cbegin(), v1.cend(), std::back_inserter(li_even), is_even_pred);
for (auto i : li_even)
std::cout << i << ", ";
std::cout << std::endl;
}
该程序看起来运行良好,但在我的 cpy_if
算法中使用 decltype
的上下文是否正确?因为我只让算法有两种被认为是迭代器的元素类型。?感谢您提供任何帮助、提示和建议。
您可以将谓词的类型作为模板参数并使用函数模板参数推导。如需更多灵感(和可能的实施技巧):
https://en.cppreference.com/w/cpp/algorithm/copy
而不是 decltype(*first)
或 decltype(*first + 1)
它被认为更适合使用
typename iterator_traits<T>::value_type
明显的问题是 *first + 1
对某些类型不起作用。
我假设你添加它是为了防止 decltype
给你一个参考。如果是这样,更可靠的等价物是:
bool(*pfnPred)(std::remove_cv_t<std::remove_reference_t<decltype(*first)>>)
从C++20开始,可以简写为:
bool(*pfnPred)(std::remove_cvref_t<decltype(*first)>)
接下来,使用函数指针会对谓词施加不必要的限制。
它不允许您使用有状态的 lambda 或参数类型略有不同的函数(例如 bool pred(const int &) {...}
)。
您可以让您的函数接受任意可调用对象,而不是使用函数指针。 (这就是标准算法的工作原理。)
template <class T, class U, class F>
void cpy_if(T first, T last, U destIt, F pfnPred) {
while (first != last) {
if (pfnPred(*first))
*destIt++ = *first;
++first;
}
}
为了额外的安全,您可以使用 pfnPred(std::as_const(*first))
来防止谓词通过非常量引用接受参数并修改它。
你好,我被要求在这个例子中模拟算法 std::copy_if
,将奇数复制到 s list
个整数中,偶数也复制到另一个列表中,所以这是我的例子:
#include <list>
#include <vector>
#include <iostream>
template <typename T>
bool is_odd_pred(T x) {
return x % 2 != 0;
}
template <typename T>
bool is_even_pred(T x) {
return !(x % 2);
}
template <class T, class U>
void cpy_if(T first, T last, U destIt, bool(*pfnPred)(decltype(*first + 1))) {
while (first != last) {
if (pfnPred(*first))
*destIt++ = *first;
++first;
}
}
int main() {
std::vector<int> v1{ 10, 27, 57, 77, 81, 24, 16, 23, 28 };
for (auto i : v1)
std::cout << i << ", ";
std::cout << std::endl;
std::list<int> li_odd;
//cpy_if(v1.cbegin(), v1.cend(), li.begin(),
// [](decltype(*v1.cbegin() + 1) a) { return (a % 2 != 0); });
cpy_if(v1.cbegin(), v1.cend(), std::back_inserter(li_odd), is_odd_pred);
for (auto i : li_odd)
std::cout << i << ", ";
std::cout << std::endl;
std::list<int> li_even;
cpy_if(v1.cbegin(), v1.cend(), std::back_inserter(li_even), is_even_pred);
for (auto i : li_even)
std::cout << i << ", ";
std::cout << std::endl;
}
该程序看起来运行良好,但在我的 cpy_if
算法中使用 decltype
的上下文是否正确?因为我只让算法有两种被认为是迭代器的元素类型。?感谢您提供任何帮助、提示和建议。
您可以将谓词的类型作为模板参数并使用函数模板参数推导。如需更多灵感(和可能的实施技巧): https://en.cppreference.com/w/cpp/algorithm/copy
而不是 decltype(*first)
或 decltype(*first + 1)
它被认为更适合使用
typename iterator_traits<T>::value_type
明显的问题是 *first + 1
对某些类型不起作用。
我假设你添加它是为了防止 decltype
给你一个参考。如果是这样,更可靠的等价物是:
bool(*pfnPred)(std::remove_cv_t<std::remove_reference_t<decltype(*first)>>)
从C++20开始,可以简写为:
bool(*pfnPred)(std::remove_cvref_t<decltype(*first)>)
接下来,使用函数指针会对谓词施加不必要的限制。
它不允许您使用有状态的 lambda 或参数类型略有不同的函数(例如 bool pred(const int &) {...}
)。
您可以让您的函数接受任意可调用对象,而不是使用函数指针。 (这就是标准算法的工作原理。)
template <class T, class U, class F>
void cpy_if(T first, T last, U destIt, F pfnPred) {
while (first != last) {
if (pfnPred(*first))
*destIt++ = *first;
++first;
}
}
为了额外的安全,您可以使用 pfnPred(std::as_const(*first))
来防止谓词通过非常量引用接受参数并修改它。