是否有可能强制编译器在我的类中传播const-qualifier,以便为构造函数提供const指针?请考虑以下代码:
struct T
{
T(int * a, int * b):
a(a), b(b) {}
int * a;
int * b;
};
int a = 1, b = 2;
const int * aRef = &a;
const int * bRef = &b;
const T obj(aRef, bRef); // error
显然不允许这样做,因为构造函数接受int *
,而不是const int *
。有没有办法达到相同的效果,如果无意修改类a
的{{1}}对象中b
和const
的数据? / p>
编辑这是一个稍微复杂的例子,更接近实际问题。想象一下,我按顺序传递了许多T
的大数组(比如连续1000个整数),我想评估int[]
中位置的最大元素运行(即运行最大值)也是1000-int vector)。当我将k
传递给传入数组的开头时,我设计了一个struct
const int *
struct ArrayWithMax
{
public:
ArrayWithMax(int * array) : array(array) {}
void Max(const ArrayWithMax& rhs);
private:
int * array;
}
显然会循环遍历两个数组,并将最大值(ArrayWithMax::Max
)分配给对象max(this->array[k], rhs.array[k]
。为简洁起见,我将跳过代码。
现在,我将存储结果的变量必须是非常量的(因为max-array的元素将会改变)。但是,我收到的更新是array
。对我来说最简单的方法是从const int *
初始化const ArrayWithMax
,这正是问题试图实现的目标。
答案 0 :(得分:3)
看起来你想要的是:
const T obj(aRef, bRef);
导致一个对象无法修改指针所指向的整数。这意味着让成员指针为int const* const
或int const*
。
现实是const
只是传播给成员,使它们都成为int* const
,这只是意味着一旦指针被设置,它们就无法改变。
您可以通过以下方式实现您的目标:
template<typename Type>
struct T {
T(Type* a, Type* b):
a(a), b(b) {}
Type* a;
Type* b;
};
然后:
int a = 1, b = 2;
int const* aRef = &a;
int const* bRef = &b;
T<int const> obj(aRef, bRef);
如果您还希望指针本身为const
,则可以使用:
T<int const> const obj(aRef, bRef);
答案 1 :(得分:1)
我想我明白了。您希望先使用自己的可写存储ArrayWithMax
拨打int*
,然后再使用收到的非可变存储int const *
来调用它。然后,您将这些不可变的ArrayWithMax
传递给您的可变ArrayWithMax::Max()
以评估您的最大运行时间。假设这是你想要的,我有点同意vlad_tepesch,因为设计可能需要一些工作。也就是说,我会用这样的模板来做:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <iterator>
using namespace std;
const size_t ARRAY_SIZE = 2; // hardcoded for now; it could be 1000
template <typename T>
class ArrayWithMax
{
public:
ArrayWithMax(T array) : array_(array){}
// Max will accept any class, as long as it provides U::begin() const
// Max will not be generated when type T is const.
template <typename U>
void Max(const U& rhs)
{
transform(begin(), end(), rhs.begin(), begin(),
[] (auto a, auto b) { return max(a, b); } );
}
T begin() { return array_; }
T end() { return array_+size(); }
T begin() const { return array_; }
T end() const { return array_+size(); }
size_t size() const { return ARRAY_SIZE; }
private:
T array_;
};
int main()
{
// some data to test with
int someArray[ARRAY_SIZE];
someArray[0] = 1;
someArray[1] = 2;
int const * received = someArray;
int someArray2[ARRAY_SIZE];
someArray2[0] = 0;
someArray2[1] = 8;
int const * received2 = someArray2;
// to store max
int myStorage[ARRAY_SIZE];
memset(myStorage, 0, sizeof(myStorage));
int* aWithMax = myStorage;
// first mutable ArrayWithMax with myStorage
ArrayWithMax<int*> a(aWithMax);
copy(a.begin(), a.end(), ostream_iterator<int>(cout, " "));
cout << endl;
// other ArrayWithMax with const int*
ArrayWithMax<const int*> receivedArray(received);
a.Max(receivedArray);
copy(a.begin(), a.end(), ostream_iterator<int>(cout, " "));
cout << endl;
// and another
ArrayWithMax<const int*> receivedArray2(received2);
a.Max(receivedArray2);
copy(a.begin(), a.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}
该程序编译如下,它产生以下输出:
Luiss-Air:const luis$ g++-5.3.0 -std=c++14 ArrayWithMax.C
Luiss-Air:const luis$ a.out
0 0
1 2
1 8
Luiss-Air:const luis$
如果ArrayWithMax
仅计算运行最大值,请考虑使用std :: transform:
// this does what you want to do with your class
transform(aWithMax, aWithMax+ARRAY_SIZE, received, aWithMax,
[] (auto a, auto b) { return max(a, b); });
答案 2 :(得分:0)
您可以使用继承,如下所示:
struct CT
{
CT(int const * a, int const * b) :
a(a), b(b) {}
int const * ca;
int const * cb;
};
struct T : CT
{
T(int * a, int * b) :
CT(a, b) {}
int * a() const { return const_cast<int *>(ca); }
int * b() const { return const_cast<int *>(cb); }
};
或者,您可以制作CT
和T
个不相关的类型,并提供从T
到CT
的隐式转换。
我真的不希望通过const T
与T
进行此操作。这是非直观的。此外,您还必须禁用默认的copy-ctor。否则,总是可以从const-ref创建非const副本,然后使用该非const副本来修改*a
或*b
。