When you write a constructor, you have the opportunity to test the values of the arguments from out of range or other unwanted situations in its body.
class a
{
int b;
public:
a(int c)
{
if(c < MIN_ALLOWED || c > MAX_ALLOWED)
{
// Take some measure
}
else
{
b = c;
}
}
};
But when you're dealing with const members, they should be initialized by means of an initializer list, so, in this case, how to prevent unwanted values?
class a
{
const int b;
public:
a(int c) : b(c)
{
// How to control "c" value?!...
}
};
Make a function:
class a {
int const b;
public:
a(int const c)
: b { initializeB(c) }
{
}
private:
static int initializeB(int const c)
{
if (c < MIN_ALLOWED || c > MAX_ALLOWED) {
// Take some mesure
return -1; // example
}
return c;
}
};
class a
{
const int b;
public:
a(int c) : b((c < MIN_ALLOWED || c > MAX_ALLOWED) ? throw std::logic_error("bad") : c)
{
// How to control "c" value?!...
}
};
You can delegate the verification and modification of the variable to a function.
class a {
public:
a(int c) : b(ValidateAndTransformInputParameter(c)) {}
private:
const int b;
int ValidateAndTransformInputParameter(int d) const {
if (d < 100) {
d = 100;
}
return d;
}
};
There are three major ways:
Chain the validation with the comma-operator:
a(int c) : b(validate(c), c) {}
Remember that the initializers are executed strictly depth-first, in declaration order, ignoring virtual inheritance.
Using the ternary operator:
a(int c) : b(validate(c) ? c : throw 0) {}
This needs the least amount of folderol if it's really a one-off.
Using a transforming and validating class or function:
a(int c) : b(process(c)) {}
Optionally, they might be combined with ctor-chaining, especially if more than one result comes from processing the inputs:
private:
struct process {
...
};
a(process x) : b(x.b), c(x.c), d(x.d) {}
public:
a(int c) : a(process(c)) {}
All of the above answers are good and work... but lest we forget, you can also do:
class a
{
public:
a(int c) : b([=]() -> int {
if (c < MIN_ALLOWED || c > MAX_ALLOWED)
throw std::logic_error("b");
return c;
}()) {}
private:
int b;
};
It looks awful in my opinion though, having a lambda in an initializer list, but it's still possible.
Related
You can redefine operator << in class by overload it.
However, how do you code it so that it would operates specific to a certain class member?
for example
class C
{
int a;
double b;
}
// I would like something like
void main ()
{
C c;
c.a << 1; // sets class member a to value 1;
}
I want a operator defined in Class C that operates specifically to class member a.
a pesudo-code would be
class C
{
int a;
double b;
void operator << (istream & fin)
{
... fin.get()... some code
}
}
Stating the obvious for a moment, assuming the variable is public, you'd use:
class C
{
int a;
double b;
}
// I would like something like
void main ()
{
C c;
c.a = 1; // sets class member a to value 1;
}
The << and >> operators are bit shifts, which have their own meaning. Overloading those for your own purpose is probably a bad idea.
The C++ way of doing things is to avoid setting member variables externally where possible (e.g. using RAII approaches, to set data at initialisation)....
class C
{
public:
C(int a, double b) : a(a), b(b) {}
int getA() const { return a; }
double getB() const { return b; }
private:
int a;
double b;
};
.... Or by adding a setter method if you really need it, e.g.
class C
{
public:
C(int a, double b) : a(a), b(b) {}
int getA() const { return a; }
double getB() const { return b; }
void setA(int v) { a = v; }
void setB(double v) { b = v; }
private:
int a;
double b;
};
You could in theory generate a new type, and overload the operators for that type, but it's not something I'd recommend (because changing the meaning of an operator is almost always a bad idea)
struct MyIntType {
int i;
// overload cast operator
operator int () {
return i;
}
// assign
MyIntType& operator = (const int& v) {
i = v;
return *this;
}
// not recommended :(
MyIntType& operator << (const int& v) {
i = v;
return *this;
}
};
class C
{
public:
MyIntType a;
double b;
};
void main ()
{
C c;
c.a << 1;
}
Having read your comment above, it sounds like you want to do this:
class C
{
public:
// I'm still not recommending this :(
C& operator << (const int& v) {
a = v;
return *this;
}
private:
int a;
double b;
};
void main ()
{
C c;
c << 1; //< now sets c.a
}
I want to make a class/struct where one of the attributes is functionally dependent on other attributes. How can this be achieved?
struct Numbers {
int a;
int b;
int c; // c == a+b
}
Numbers n1 {1, 2, 3}; // Ok.
Numbers n2 {1, 2, 4}; // Error!
In my use case, a, b, c are constant, if that matters (so const int may be used).
All attributes will appear many times in class/struct methods, so the goal is to cache the value a+b. Addition is used as an example, the dependency function may be more complex.
If a and b are mutable then you can't enforce that c is kept in sync; all three would have to be const for you to enforce this invariant.
The simplest approach would be to make c a function:
struct Numbers {
int a;
int b;
int c() const { return a + b; }
}
If you want the value of c to be cached instead of computed when needed then you need to hide a and b behind accessors as well so that you can update c when they are updated.
class Numbers {
public:
Numbers(int a, int b) : ma{a}, mb{b} { updateC(); }
int a() const { return ma; }
int b() const { return mb; }
int c() const { return mc; }
void a(int v) { ma = v; updateC(); }
void b(int v) { mb = v; updateC(); }
// No setter for c
private:
void updateC() { mc = ma + mb; }
int ma;
int mb;
int mc;
};
You can do something like that:
struct Numbers {
Numbers(int a, int b) : a(a), b(b), c(a + b) {}
private:
int a;
int b;
int c; // c == a+b
};
Edit:
To keep the values of a and b updated, and to get the values of those variables, you'll have to use get & set methods, like in #cdhowie response.
I have a small problem at hand. Suppose there is a if condition with only 2 operands but I want to make the operation dynamic.
void somFunc()
{
if(a && b) /*1*/
{
}
else if(a1 && b1) /*2*/
{
}
else if(a || b) /*3*/
{
}
else if(a1 || b1) /*4*/
}
Basically, 1 and 3 exactly has same parameters with different operation,Similarly for 2 and 4. I want to reduce these 4 operations to 2.
I want to know if there is a way I can make oper dynamic. Consider we only have 2 operations && and ||Can I use templates in any way ?
If someone wants to know why I need this is, there are n if conditions inside a big if/else. If I somehow achieve this, I reduce the conditions by half.
Not sure if this is what you are asking for, but you can write something like this:
enum OPERATION { AND, OR };
bool operation(bool a, bool b,OPERATION op) {
if (op == AND) return a && b;
return a || b;
}
void somFunc(OPERATION op)
{
if(operation(a,b,op))
{
}
}
Or as suggested in a comment, make the operation to be performed a parameter of the function, like so
template <OPERATION>
void somFunc(OPERATION op)
{
if(op(a,b))
{
}
}
and call it like this
somFunc( [](bool a, bool b) { return a && b; });
somFunc( [](bool a, bool b) { return a || b; });
You can use pointers to funtions.
#include <iostream>
#include <functional>
bool oper1(bool a, bool b) {
return a || b;
}
bool oper2(bool a, bool b) {
return a && b;
}
int main() {
bool a = true, b = false;
auto oper = oper1;
if (oper(a, b)) {
std::cout << "OR\n";
}
oper = oper2;
if (oper(a, b)) {
std::cout << "AND\n";
}
}
First you define all your conditions and later you can switch the condition by setting the variable.
You can also use inheritance and functors:
#include <iostream>
#include <functional>
#include <memory>
class Operator {
public:
virtual bool eval(bool a, bool b) = 0;
};
class OrOperator : public Operator {
public:
bool eval(bool a, bool b) {
return a || b;
}
};
class AndOperator : public Operator {
public:
bool eval(bool a, bool b) {
return a && b;
}
};
class VariableOperator : public Operator {
public:
VariableOperator(bool val) : val(val) {}
bool eval(bool a, bool b) {
return val;
}
private:
bool val;
};
int main() {
bool a = true, b = false;
std::unique_ptr<Operator> oper(new OrOperator);
if (oper->eval(a, b)) {
std::cout << "OR\n";
}
oper.reset(new AndOperator);
if (oper->eval(a, b)) {
std::cout << "AND\n";
}
oper.reset(new VariableOperator(true));
if (oper->eval(a, b)) {
std::cout << "VARIABLE\n";
}
}
You might be looking for something like this:
void somFunc()
{
std::vector< std::function< bool(bool, bool) > > operators = {
[](bool a, bool b){ return a && b; },
[](bool a, bool b){ return a || b; }
};
for ( auto& op : operators )
{
if ( op( a, b ) )
{
}
else if ( op( a1, b1 ) )
{
}
}
}
You can add more operators or change the parameter types easily enough.
You can do this with CRTP too:
#include <iostream>
#include <string>
#include <memory>
template<class T>
class Operation
{
public:
bool eval(bool a, bool b)
{
return this->impl().eval(a,b);
}
private:
T& impl() { return static_cast<T&>(*this); }
};
class AndOperation : public Operation<AndOperation>
{
public:
bool eval(bool a, bool b)
{
return a && b;
}
};
class OrOperation : public Operation<OrOperation>
{
public:
bool eval(bool a, bool b)
{
return a || b;
}
};
int main()
{
AndOperation andOp;
auto anonOp = std::make_unique<OrOperation>();
std::cout << andOp.eval(true, true) << std::endl;
std::cout << anonOp->eval(false,false);
}
see live example here
What are the advantages of CRTP over virtual inheritance?
CRTP is a case of static polymorphism. Here's some references:
Compile time vs run time polymorphism in C++ advantages/disadvantages
What is the motivation behind static polymorphism in C++?
C++: How is this technique of compile-time polymorphism called and what are the pros and cons?
The cost of dynamic (virtual calls) vs. static (CRTP) dispatch in C++
It is possible to make somFunc() a template, and accept any function that accepts two arguments and returns a value that can be tested with if.
#include <functional> // for binary operations in std
template<class Operation> void somfunc(Operation oper)
{
if (oper(a,b))
{
// whatever
}
}
int main()
{
somFunc(std::logical_and<int>());
somFunc(std::logical_or<int>());
somFunc(std::plus<int>()); // addition
// pass a lambda
somFunc([](int a, int b) -> int {return a + b;}); // lambda form of addition
}
In the above, I've assumed the variables a and b (which have been used in the question, but types unspecified) are of type int.
I have some C++ code. I'm duplicating a pattern repeatedly in it which isn't pleasant.
class layerclass {
public:
vector<int> a;
vector<int> b;
vector<int> c;
bool isInA(int x) { return a.find(x) != a.end(); } // true if x is in a
bool isInB ...
bool isInC ...
};
class innerlayer : public layerclass {
public:
layerclass *outerlayer;
bool isInA(int x) {
if (layerclass::isInA(x)) return true;
return outerlayer->isInA(x);
}
bool isInB(int x) ... // these two fn's will be identical to isInA()
bool isInC(int x) ... // with the exception of calling isInB/C()
};
In my case there really are only about 3 containers to search this way, but it's very bothersome for me to see. A solution might be to tag-dispatch somehow:
class layerclass {
public:
vector<int> a;
vector<int> b;
vector<int> c;
enum class members { a, b, c };
bool isIn(int x, members m) {
switch (m) {
case members::a: return a.find(x) != a.end();
...
}
};
class innerlayer : public layerclass {
public:
layerclass *outerlayer;
bool isIn(int x, member m) {
if (layerclass::isIn(x, m) return true;
return outerlayer->isIn(x, m);
}
};
Ok that's a little better but I still have the duplicated code in layerclass::isIn() and have to maintain the enum. Is this the best I cand do in C++? Do other languages offer a convenient solution to this outside of something like a preprocessor macro?
You can rewrite the class as follows, so there is no duplicate code in isIn
class layerclass {
public:
vector<int> a;
vector<int> b;
vector<int> c;
bool isIn(vector<int> &vec, int x) { return vec.find(x) != a.end(); }
bool isInA(int x) { return isIn(a, x); }
bool isInB(int x) { return isIn(b, x); }
bool isInC(int x) { return isIn(c, x); }
};
Is the following code valid C++? Otherwise, is there a valid way to simultaneously interpret memory as values of different type?
#include <cstdio>
struct Base { int payload; };
struct D1 : Base { void operator()(){ printf("D1: %d\n", payload);} };
struct D2 : Base { void operator()(){ printf("D2: %d\n", payload);} };
int main()
{
D1 d1;
D2& d2 = static_cast<D2&>(static_cast<Base&>(d1));
d1();
d2();
d2.payload = 3;
d1();
d2();
}
In response to #NickoPo: My use case is basically what follows. Imagine that IntBase is not necessarily cheap to copy, that there are many complex algorithms, some of which profit from numbers being prime vs. odd, and others don't:
#include <cassert>
#include <cstdio>
bool is_odd(int value) { return 0 != value % 2; }
bool is_small_prime(int value) { return 2 == value || 3 == value || 5 == value || 7 == value; }
class IntBase
{
public:
explicit IntBase(int value) : m_value(value) {}
int value() const { return m_value; }
protected:
int m_value;
};
class OddInt : public IntBase
{
public:
explicit OddInt(int value) : IntBase(value) { assert(is_odd(m_value)); }
};
class SmallPrimeInt : public IntBase
{
public:
explicit SmallPrimeInt(int value) : IntBase(value) { assert(is_small_prime(m_value)); }
};
bool is_constrainable_to_odd_int(IntBase const& x)
{
return is_odd(x.value());
}
OddInt const& constrain_to_odd_int(IntBase const& x)
{
assert(is_odd(x.value()));
return static_cast<OddInt const&>(x);
}
bool is_constrainable_to_small_prime_int(IntBase const& x)
{
return is_small_prime(x.value());
}
SmallPrimeInt const& constrain_to_small_prime_int(IntBase const& x)
{
assert(is_small_prime(x.value()));
return static_cast<SmallPrimeInt const&>(x);
}
void algorithm(IntBase const&)
{
printf("algoritm(IntBase const&)\n");
}
void algorithm(OddInt const&)
{
printf("algoritm(OddInt const&)\n");
}
void algorithm(SmallPrimeInt const&)
{
printf("algoritm(SmallPrimeInt const&)\n");
}
void test(IntBase const& x)
{
if (is_constrainable_to_small_prime_int(x))
{
algorithm(constrain_to_small_prime_int(x));
}
else if (is_constrainable_to_odd_int(x))
{
algorithm(constrain_to_odd_int(x));
}
else
{
algorithm(x);
}
}
void test(OddInt const& x)
{
if (is_constrainable_to_small_prime_int(x))
{
algorithm(constrain_to_small_prime_int(x));
}
else
{
algorithm(constrain_to_odd_int(x));
}
}
int main()
{
IntBase x(0);
OddInt y(1);
OddInt z(7);
test(x); // algoritm(IntBase const&)
test(y); // algoritm(OddInt const&)
test(z); // algoritm(SmallPrimeInt const&)
}
Related:
Can I legally reinterpret_cast between layout-compatible standard-layout types?
Answer to Safety of casting between pointers of two identical classes?
If you're going to cast while using similar interfaces while using type as a guarantee, I'd recommend that you just wrap the inner data with your new object type and then provide access to the inner data in order to transfer it from one type to another. There's no point in doing static casting or reinterpret casting if you're not going to do it safely.
Here's an example:
http://coliru.stacked-crooked.com/a/40d5efeff22fcdcd
#include <iostream>
//Base data structure to encapsulate only data.
struct data {
data(int i) : i(i) {}
int i;
};
//Wrapper around our data structure, with interfaces to access
//the values and the data; implement your own constructor to
//gate the value
class PrimeInt {
public:
PrimeInt(const int i)
: d(i) {}
PrimeInt(const data& other)
: d(other) {}
PrimeInt(data&& other)
: d(std::move(other)) {}
PrimeInt& operator=(const PrimeInt&) = default;
PrimeInt& operator=(PrimeInt&&) = default;
int get() {return d.i;};
operator data() {return d;};
private:
data d;
};
//Wrapper around our data structure, with interfaces to access
//the values and the data; implement your own constructor to
//gate the value
class OddInt {
public:
OddInt(const int i)
: d(i) {}
OddInt(const data& other)
: d(other) {}
OddInt(data&& other)
: d(std::move(other)) {}
OddInt& operator=(const OddInt&) = default;
OddInt& operator=(OddInt&&) = default;
int get() {return d.i;};
operator data() {return d;};
private:
data d;
};
//Notice that we can now implicitly cast from one type to another.
int main() {
PrimeInt pi(10);
std::cout << pi.get() << std::endl;
OddInt oi(pi);
std::cout << oi.get() << std::endl;
return 0;
}
If your objects are not cheap to copy, you are probably passing pointers or references everywhere. You can wrap pointers to your common base in different class types and pass them by value. That is, instead of this (pseudocode)
class B
class D1 : B { ... }
class D2 : B { ... }
D1* d1; D2* d2;
you have
class Bimpl
class B { Bimpl* bimpl; }
class D1 : B { ... }
class D2 : B { ... }
D1 d1; D2 d2;
Here you never do any built-in cast. If you want to convert D1 to D2, you write your own conversion function.