原始指针隐式转换为const指针,需要与用户类型相同

时间:2015-09-02 23:50:32

标签: c++ templates const implicit-conversion

如果我有一个模板函数接受指向模板类型的指针:

template<typename T>
void foo(const T* x);

它自然接受指向非const对象的指针:

int* x = ...;
foo(x); //int* implicitly converted to const int *

我想对具有指针语义的模板类做同样的事情。

例如,最近提出的array_view类是一个连续内存块的视图,它具有(非拥有)指针语义,可用于引用可变项或const项的数组: / p>

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'

即使我添加了在Tconst T变体之间进行转换的复制构造函数或转换运算符,编译器也无法解析模板的T

我知道有2种解决方法:

  • 在调用时显式指定模板参数:foo<int>(x)
  • 写一个更通用的模板:template<typename U> void foo(U x)并可能使用元编程约束U

有更好的解决方案吗?

1 个答案:

答案 0 :(得分:1)

显而易见的解决方案是使用

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 - 由论证的const隐含地强制执行。对于指针参数,如果推导出指针类型,则BTW为true:

template <typename T>
void bar(T*);

使用bar()调用int const*时,类型T会被推断为T constconst版本的主要需求是已经推断出类型,但参数应该适合。但是,在这种情况下,std::array_view<...>转换同样有效。