原始指针隐式转换为常量指针,需要与用户类型相同
Raw pointer implicitly converts to const pointer, need the same with user type
如果我有一个接受模板类型指针的模板函数:
template<typename T>
void foo(const T* x);
它自然接受指向非常量对象的指针:
int* x = ...;
foo(x); //int* implicitly converted to const int *
我想对具有指针语义的模板 class 执行相同的操作。
例如,最近提出的 array_view class,它是对连续内存块的视图,具有(非拥有)指针语义,可用于引用数组可变或常量项:
array_view<int> av = ...;
av[0] = 1;
array_view<const int> cav = ...;
cav[0] = 1; // <- error: read-only variable is not assignable
问题是上面的原始指针模式不起作用:
template<typename T>
void foo(array_view<const T> x);
...
array_view<int> x;
foo(x); // <- error: no matching function for call to 'foo'
即使我添加了在 T
和 const T
变体之间转换的复制构造函数或转换运算符,编译器也无法解析模板的 T
。
我知道 2 个解决方法:
- 调用时显式指定模板参数:
foo<int>(x)
- 编写一个更通用的模板:
template<typename U> void foo(U x)
并可能 U
使用元编程进行约束。
有更好的解决方案吗?
显而易见的解决方案是使用
template <typename T>
void foo(std::array_view<T> x);
有趣的是,这适用于两种形式的数组视图:
int array[] = { 1, 2, 3 };
foo(array_view<int>(std::begin(array), std::end(array)));
foo(array_view<int const>(std::begin(array), std::end(array)));
参数的 const
-ness 由参数的 const
-ness 隐式强制执行。顺便说一句,如果推导指针对象类型,指针参数也是如此:
template <typename T>
void bar(T*);
当使用 int const*
调用 bar()
时,类型 T
被推断为 T const
。 const
版本的主要需求是当类型已经推导出来但参数应该适合时。但是,在那种情况下,std::array_view<...>
转换同样有效。
如果我有一个接受模板类型指针的模板函数:
template<typename T>
void foo(const T* x);
它自然接受指向非常量对象的指针:
int* x = ...;
foo(x); //int* implicitly converted to const int *
我想对具有指针语义的模板 class 执行相同的操作。
例如,最近提出的 array_view class,它是对连续内存块的视图,具有(非拥有)指针语义,可用于引用数组可变或常量项:
array_view<int> av = ...;
av[0] = 1;
array_view<const int> cav = ...;
cav[0] = 1; // <- error: read-only variable is not assignable
问题是上面的原始指针模式不起作用:
template<typename T>
void foo(array_view<const T> x);
...
array_view<int> x;
foo(x); // <- error: no matching function for call to 'foo'
即使我添加了在 T
和 const T
变体之间转换的复制构造函数或转换运算符,编译器也无法解析模板的 T
。
我知道 2 个解决方法:
- 调用时显式指定模板参数:
foo<int>(x)
- 编写一个更通用的模板:
template<typename U> void foo(U x)
并可能U
使用元编程进行约束。
有更好的解决方案吗?
显而易见的解决方案是使用
template <typename T>
void foo(std::array_view<T> x);
有趣的是,这适用于两种形式的数组视图:
int array[] = { 1, 2, 3 };
foo(array_view<int>(std::begin(array), std::end(array)));
foo(array_view<int const>(std::begin(array), std::end(array)));
参数的 const
-ness 由参数的 const
-ness 隐式强制执行。顺便说一句,如果推导指针对象类型,指针参数也是如此:
template <typename T>
void bar(T*);
当使用 int const*
调用 bar()
时,类型 T
被推断为 T const
。 const
版本的主要需求是当类型已经推导出来但参数应该适合时。但是,在那种情况下,std::array_view<...>
转换同样有效。