如何获取以下代码进行编译?我想支持提供给构造函数的c样式数组和std :: array的所有常量性变体。
#include <cstddef>
#include <array>
template <typename T>
class Base
{
public:
explicit Base(T* data) : data_(data) {}
private:
T* data_;
};
template <typename T, std::size_t S>
class A : public Base<T>
{
public:
explicit A(T (&array)[S]) : Base<T>(array) { ; }
template <template <typename, std::size_t> class C>
explicit A(C<T, S>& c) : Base<T>(c.begin())
{
;
}
template <template <typename, std::size_t> class C>
explicit A(C<T, S> const& c) : Base<T>(c.begin())
{
;
}
};
int main()
{
constexpr std::size_t size{5U};
int c_style_array[size] = {2, 6, 7, 8, 3};
A<int, size> a(c_style_array); // OK
int const c_style_array_const[size] = {2, 6, 7, 8, 3};
A<int const, size> b(c_style_array_const); // OK
std::array<int, size> std_array = {2, 6, 7, 8, 3};
A<int, size> c(std_array); // OK
std::array<int const, size> std_array_const_1 = {2, 6, 7, 8, 3};
A<int const, size> d(std_array_const_1); // OK
std::array<int const, size> const std_array_const_2 = {2, 6, 7, 8, 3};
A<int const, size> e(std_array_const_2); // OK
std::array<int, size> const std_array_const_3 = {2, 6, 7, 8, 3};
A<int, size> f(std_array_const_3); // NOT OK
}
错误消息:
*a.cpp: In instantiation of ‘A<T, S>::A(const C<T, S>&) [with C = std::array; T = int; long unsigned int S = 5]’:
a.cpp:46:37: required from here
a.cpp:26:53: error: invalid conversion from ‘std::array<int, 5>::const_iterator {aka const int*}’ to ‘int*’ [-fpermissive]
explicit A(C<T, S> const& c) : Base<T>(c.begin())
^
a.cpp:7:14: note: initializing argument 1 of ‘Base<T>::Base(T*) [with T = int]’
explicit Base(T* data) : data_(data) {}*
以下声明
std::array<int, size> const std_array_const_3 = {2, 6, 7, 8, 3};
A<int, size> f(std_array_const_3); // NOT OK
无效,因为A<int, size>
继承自包含Base<int>
的int *
,并且您尝试使用std_array_const_3.begin()
对其进行初始化,并返回一个可以大致视为int const *
的常量迭代器。
而且,显然,您无法使用int *
初始化int const *
。
在我看来f
应该是A<int const, size>
,而不是A<int, size>
。不幸的是A<int const, size>
无法从std::array<int, size> const
初始化。
因此,我建议在A
中添加以下构造函数来管理这种特殊情况
template <template <typename, std::size_t> class C,
typename U = typename std::remove_const<T>::type>
explicit A(C<U, S> const & c) : Base<T>(c.begin())
{ }
此解决方案使用std::remove_const
,从C ++ 11开始可用,但是我想您可以在C ++ 98 / C ++ 03中轻松创建它的替代品。
一种替代方法是修改C<T, S> const &
构造函数以匹配两种情况,如下所示
template <typename U, template <typename, std::size_t> class C,
std::enable_if_t<std::is_same_v<U const, T const>, bool> = true>
explicit A(C<U, S> const & c) : Base<T>(c.begin())
{ }
也用于std::enable_if_t
和std::is_same_v
,我想你应该能够构造C ++ 98 / C ++ 03替代品。