const 指针的模板参数推导失败
Template argument deduction failing for const pointers
我不明白为什么在这种情况下模板参数推导失败:
template<class Iterator> void
f(Iterator x, const Iterator y) {}
int main()
{
const int* cpi;
int* pi;
f(pi,cpi);
}
为什么第二个参数Iterator
不推导出int*
?
f
最地道的声明是什么?
迭代器可以是 int *
或 const int *
。第二个函数参数的限定符 const 表示 int * const
或 const int * const
.
您可以创建特征来检查迭代器是否是常量值的迭代器。
#include <iterator> // iterator_traits
#include <type_traits> // is_const_v, remove_pointer_t, enable_if_t
template<typename T>
struct is_const_iterator {
// Define a pointer type to the type iterated over. Something already a pointer
// will still be a pointer
using pointer = typename std::iterator_traits<T>::pointer;
// Remove the pointer part from the type and check for constness.
static const bool value = std::is_const_v<std::remove_pointer_t<pointer>>;
};
// Helper variable template to simplify the use of the above.
template<class T>
inline constexpr bool is_const_iterator_v = is_const_iterator<T>::value;
SFINAE 使用 is_const_iterator_v
template<class It, class CIt, std::enable_if_t<is_const_iterator_v<CIt>, int> = 0>
void f(It x, CIt y) {
//for(; x != y; ++x) std::cout << *x << '\n';
}
或者,如果您的函数没有其他重载(不需要 SFINAE),您可以使用 static_assert
让用户更清楚:
template<class It, class CIt>
void f(It x, CIt y) {
static_assert(is_const_iterator_v<CIt>, "Arg 2 must be a const iterator");
//for(; x != y; ++x) std::cout << *x << '\n';
}
示例:
#include <iostream>
#include <vector>
int main() {
int values[]{1, 2};
int* pi = values;
const int* cpi = values + std::size(values);
std::vector<int> v{3, 4};
f(pi, cpi);
f(v.begin(), v.cend());
// f(pi, pi); // error, pi is non-const
// f(v.begin(), v.end()); // error v.end() is non-const
}
我不明白为什么在这种情况下模板参数推导失败:
template<class Iterator> void
f(Iterator x, const Iterator y) {}
int main()
{
const int* cpi;
int* pi;
f(pi,cpi);
}
为什么第二个参数Iterator
不推导出int*
?
f
最地道的声明是什么?
迭代器可以是 int *
或 const int *
。第二个函数参数的限定符 const 表示 int * const
或 const int * const
.
您可以创建特征来检查迭代器是否是常量值的迭代器。
#include <iterator> // iterator_traits
#include <type_traits> // is_const_v, remove_pointer_t, enable_if_t
template<typename T>
struct is_const_iterator {
// Define a pointer type to the type iterated over. Something already a pointer
// will still be a pointer
using pointer = typename std::iterator_traits<T>::pointer;
// Remove the pointer part from the type and check for constness.
static const bool value = std::is_const_v<std::remove_pointer_t<pointer>>;
};
// Helper variable template to simplify the use of the above.
template<class T>
inline constexpr bool is_const_iterator_v = is_const_iterator<T>::value;
SFINAE 使用 is_const_iterator_v
template<class It, class CIt, std::enable_if_t<is_const_iterator_v<CIt>, int> = 0>
void f(It x, CIt y) {
//for(; x != y; ++x) std::cout << *x << '\n';
}
或者,如果您的函数没有其他重载(不需要 SFINAE),您可以使用 static_assert
让用户更清楚:
template<class It, class CIt>
void f(It x, CIt y) {
static_assert(is_const_iterator_v<CIt>, "Arg 2 must be a const iterator");
//for(; x != y; ++x) std::cout << *x << '\n';
}
示例:
#include <iostream>
#include <vector>
int main() {
int values[]{1, 2};
int* pi = values;
const int* cpi = values + std::size(values);
std::vector<int> v{3, 4};
f(pi, cpi);
f(v.begin(), v.cend());
// f(pi, pi); // error, pi is non-const
// f(v.begin(), v.end()); // error v.end() is non-const
}