严格来说,类型是 C++ 中的编译时构造。然而,有时对象的一些常量运行时特性被有效地定义为运行时类型。
例如,如果有一个几何向量,其中,由于框架限制,尺寸仅在运行时已知(否则我会将尺寸设为模板参数),例如从文件中读取。
维度是运行时这一事实并不意味着应该能够比较、分配或组合具有不同维度的向量。如果想在代码中引入这种逻辑,就必须限制一堆操作。这可以通过断言或抛出来完成,仅在运行时。
所以,例如,一个人会实现这个,
class vec{
std::vector<double> impl_;
public:
vec(std::size_t size) : impl_(size){}
bool operator==(vec const& other) const{
if(impl_.size() != other.impl_.size()) throw std::domain_error("cannot compare vectors of different size");
return std::equal(impl_.begin(), impl_.end(), other.impl_.begin());
}
bool operator<(vec const& other) const{
if(impl_.size() != other.impl_.size()) throw std::domain_error("cannot compare vectors of different size");
return impl_ < other.impl_;
}
vector& operator=(vector const& other){
if(impl_.size() != other.impl_.size()) throw std::domain_error("");
std::copy(other.impl_.begin(), other.impl_.end(), impl_.begin());
return *this;
}
};
vec
实施std::vector
后尺寸不会改变。
这样做的问题是,最终会在所有函数中编写限制。
我的问题是,是否有任何习惯用法或工具可以通过限制(在运行时)使用不兼容对象执行的操作,特别是帮助编写更少重复的代码来帮助解决这个问题。
int v1_dim = 4;
int v2_dim = 3;
vec v1(v1_dim); // v1 has (forever) dimension 4, 4 is essential to v1
vec v2(v2_dim); // v2 has (forever) dimension 3
v1 = v2; // this is a logic error, I can't prevent the compilation of this unfortunately; So I will at least do a runtime check
v1 == v2; // this is a logic error, runtime error
请注意,我不能使用std::array<double, 4>
or3>
因为4
and3
可能是运行时变量。
这个有效运行时类型的概念有名字吗?有没有被调查?
可能发生这种情况的其他示例:
1) 想象一下拥有可变大小的 NxN 数组并尝试定义数学加法。N 将是运行时的(甚至在构造后是常数),并且必须检查一个人没有添加不同大小的数组,还希望任何不兼容的比较都会触发错误。
2) 更一般地说,这个哲学问题可以出现在具有固定成员的类中。这有点做作,但假设一个人被迫拥有const
成员
struct employee{
std::string const Name; // Once the employee is created it won't change name
double salary;
employee& operator=(employee const& other);
};
可以限制这一点:
employee& employee::operator=(employee const& other){
if(Name != other.Name) throw std::domain_error("cannot change name");
salary = other.salary;
return *this;
}
我想象的唯一自动解决方案是系统地重载成员类型中的某些运算符(例如operator=() const
)以强制执行此操作。
struct employee{
My_string const Name; // Once the employee is created it won't change name
double salary;
employee& operator=(employee const& other){
Name = other.Name; //simply
salary = other.salary;
}
};
但是其中一个取决于(依赖)特殊成员类型,例如:
My_string const& My_string::operator=(My_string const& other) const{
if(*this != other) // this is the "real" inequality (not the restricted one), probably it will be if(this->std::string::operator=(other)) if My_string is derived from std::string
throw std::domain_error("assignment to const doesn't preserve value");
return *this;
}
后来为了保持一致和系统,人们会写:
employee const& employee::operator=(employee const& other) const{
if(*this != other) throw std::domain_error("assignment to const doesn't preserve value");
return *this;
}