I'm about to write a parser to read a text file line by line into structs of different types and giving these structs to a callback (observer or visitor - not sure yet).
The text file contains MT-940 data - a SWIFT bank statement.
These lines consist of a marker which specifies the type and some fields - e.g. a date - which should be parsed into type-safe members of my message. Some of these fields are optional - so my question is: How do I represent optional values in D.
C++ provides my things like boost::optional which you might know.
I currenty work around this by implementing an Optional(T) on my own (see code at the end of this post). It is a struct which contains a ValueHolder instance which might be null - which marks the case where no value has been assigned. I overwrote the copy-c'tor and the assignment operator to create a deep-copy of the ValueHolder if necessary.
Is this the way to go? Is there any other - more simple - option I just cannot see?
This is my code - not necessarily feature complete yet:
struct Optional(T)
{
class ValueHolder
{
T value;
this(T v)
{
value = v;
}
}
private ValueHolder m_value;
/* Construction without value / with value */
this(T value)
{
m_value = new ValueHolder(value);
}
/* Copy construction / assignment */
ref Optional!(T) opAssign(Optional!(T) rhs)
out
{
if (rhs.m_value !is null)
{
assert(rhs.m_value != m_value);
}
else
{
assert(m_value is null);
}
}
body
{
m_value = null;
if (rhs)
{
m_value = new ValueHolder(rhs.m_value.value);
}
return this;
}
ref Optional!(T) opAssign(T value)
out
{
assert(hasValue());
assert(m_value.value == value);
}
body
{
if (m_value is null)
{
m_value = new ValueHolder(value);
}
else
{
m_value.value = value;
}
return this;
}
this(Optional!(T) rhs)
out
{
if (rhs.m_value !is null)
{
assert(rhs.m_value != m_value);
}
else
{
assert(m_value is null);
}
}
body
{
if (rhs.m_value !is null)
{
m_value = new ValueHolder(rhs.m_value.value);
}
}
/* Implicit cast to bool */
bool hasValue() const
{
return m_value !is null;
}
X opCast(X: bool)()
{
return hasValue();
}
/* Value access */
T opUnary(string s)() const
in
{
assert(s == "*");
assert(m_value !is null);
}
body
{
return m_value.value;
}
}
/* Default Constructed Struct does not have a value assigned */
unittest
{
Optional!(int) x;
assert(x.hasValue() == false);
assert(!x);
}
/* Construction with value */
unittest
{
Optional!(int) x = 3;
assert(x);
assert(x.hasValue());
}
/* Assignment operator does copy the value */
unittest
{
Optional!(int) x = 3;
Optional!(int) y;
assert(x);
assert(!y);
y = x;
assert(&x != &y);
assert(x);
assert(y);
y = 12;
assert(x.m_value.value != y.m_value.value);
assert(*y == 12);
Optional!(int) z;
x = z;
assert(!x);
assert(!z);
assert(y);
}
For optional values, the D standard library provides the struct template Nullable in the module std.typecons.
Related
it's supposed to be an easy question, but i couldnt find the answer on google. So, how do i assign a maximum possible value to a variable?
So i want my variable to be no more than 10 as apossible value no matter what
int example;
example = ?;
You might create a custom class to handle your needs, something like:
template <int Min, int Max>
class BoundedValue
{
public:
BoundedValue(int value = Min) : mValue(Min) { set_value(value); }
int get_value() const { return mValue; }
void set_value(int value) {
if (value < Min || Max < value) {
throw std::out_of_range("!"); // Or other error handling as clamping
// value = std::clamp(value, Min, Max);
}
mValue = value;
}
BoundedValue& operator= (int value) { set_value(value); }
BoundedValue& operator ++() { set_value(mValue + 1); return *this; }
BoundedValue operator ++(int) { auto tmp = *this; ++*this; return tmp; }
// other convenient functions
operator int() const { return mValue; }
private:
int mValue = Min;
};
And then use it:
BoundedValue<0, 10> example;
++example;
example = 11; // "Error"
This question already has an answer here:
Is there a way to do constructor delegation using a conditional in C++11?
(1 answer)
Closed 4 years ago.
The typical way (and the only one widely used) to delegate some part of the object initialization to another constructor is to call it using the initializer list, like so:
class Window
{
Window(int a);
Window(int a, void *b);
Window(string a);
Window(double a, double b) : Window((int) (a + b))
{
}
};
But sometimes there is a necessity to do some prep work or branch constructor calls.
Is this how it should be done?
class Window
{
Window(int a);
Window(int a, void *b);
Window(string a);
Window(double a, double b)
{
if (a * b == 0.0)
{
Window("ZERO");
}
else if (a * b > 100.0)
{
Window((int) (a + b), x);
}
else
{
Window((int) (a + b));
}
}
};
I have never seen anything like this; this is just my guess of how it could look (which appears to be working).
Are there any side effects or any undefined behavior to calling other constructors from the constructor body (and not from the initializer list)?
#Edit: I'm including the code I'm having a problem with below. Basically, I have an object that is a container for some data, and I store it in a std::map<CString, ValueContainer>. I employ a copy constructor, and an overloaded assignment operator. The insertion works fine when I add an instance to the map using the [] operator, but it doesn't when I use the insert_or_assign method, because it uses the copy constructor (which uses the branching that is the problem here). Here's a simplification of the class.
class ValueContainer
{
ValueContainer(const VOID *p_data, ULONG p_size)
{
if (p_data != NULL)
{
if (p_size > 0)
{
if (p_size <= sizeof(shortData))
{
memcpy(shortData, p_data, p_size);
}
else
{
longData = new BYTE[p_size];
memcpy(longData, p_data, p_size);
}
}
hasValue = TRUE;
size = p_size;
}
else
{
hasValue = FALSE;
size = 0;
}
}
ValueContainer(const ValueContainer &p_value)
{
if (p_value.HasValue())
{
if (p_value.size <= sizeof(shortData))
{
ValueContainer(p_value.shortData, p_value.size);
}
else
{
ValueContainer(p_value.longData, p_value.size);
}
}
else
{
ValueContainer();
}
}
ValueContainer(VOID) : ValueContainer(NULL, 0)
{
}
ValueContainer &operator =(const ValueContainer &p_value);
{
if (p_value.hasValue)
{
if (p_value.size <= sizeof(shortData))
{
if (longData != NULL)
{
free(longData);
longData = NULL;
}
memcpy(shortData, p_value.shortData, p_value.size);
}
else
{
if (p_value.size > size)
{
longData = (BYTE *) realloc(longData, p_value.size);
}
memcpy(longData, p_value.longData, p_value.size);
}
hasValue = TRUE;
size = p_value.size;
}
else
{
if (longData != NULL)
{
free(longData);
longData = NULL;
}
hasValue = FALSE;
size = 0;
}
return *this;
}
private:
BYTE shortData[16];
BYTE *longData = NULL;
BOOL hasValue;
ULONG size;
}
For your first example, this might be the way it can be done:
class Window
{
private:
void constructor_method(int a);
void constructor_method(int a, void *b);
void constructor_method(string a);
public:
Window(int a) {
constructor_method(a);
}
Window(int a, void *b) {
constructor_method(a, b);
}
Window(string a) {
constructor_method(a);
}
Window(double a, double b)
{
if (a * b == 0.0)
{
constructor_method("ZERO");
}
else if (a * b > 100.0)
{
constructor_method((int) (a + b), x);
}
else
{
constructor_method((int) (a + b));
}
}
};
I think the short answer to this question is "simplify your code." But if that's not an option, I think the next best alternative is a factory method:
class Window
{
private:
Window(int a);
Window(int a, void *b);
Window(string a);
public:
static Window Create(double a, double b)
{
if (a * b == 0.0)
{
return Window("ZERO");
}
else if (a * b > 100.0)
{
return Window((int) (a + b), x);
}
else
{
return Window((int) (a + b));
}
}
};
I have two questions.
The first is about working with functions. I need to break out of a function at an early stage under a condition.
For example:
std::string concat(std::string& x, std::string& y, std::vector<std::string>& vec)
{
if (atoi(x.c_str()) < 0)
{
return;
}
else {
std::string concatStr = y + x;
top_back(vec);
top_back(vec);
return concatStr;
}
}
As you can see, the function must return a string, but if the string x(which i of course convert to int) is less than 0, then I theoretically should break out of the function.
The problem with writing just return; is that the compiler tells me that it needs to return a value.
The second question is how can I remove the last line from the console?
That's connected with the first question, as someone suggested that return "";
is a good workaround, but it writes a blank space into the console, which in my case with the program I'm writing is not good and causes problems.
If you can compile using C++17 you can use std::optional to allow you to optionally return something from the function. We would rewrite your function to
std::optional<std::string> concat(std::string& x, std::string& y, std::vector<std::string>& vec)
{
if (atoi(x.c_str()) < 0)
{
return {};
}
else
{
std::string concatStr = y + x;
top_back(vec);
top_back(vec);
return concatStr;
}
}
And then in the call site you can use it like
auto ret = concat(some, stuff, here)
if(ret) // only print if ret actually holds a string
std::cout << *ret;
Alternatively you could use a unique_ptr and return an empty pointer if there is no result. The function would change to
std::unique_ptr<std::string> concat(std::string& x, std::string& y, std::vector<std::string>& vec)
{
if (atoi(x.c_str()) < 0)
{
return {};
}
else
{
std::string concatStr = y + x;
top_back(vec);
top_back(vec);
return std::make_unique<std::string>(concatStr);
}
}
but the call site would remain the same.
Lastly if a blank string is never going to be a valid return from the function you could just return that and handle it in the call site like
std::string concat(std::string& x, std::string& y, std::vector<std::string>& vec)
{
if (atoi(x.c_str()) < 0)
{
return {};
}
else
{
std::string concatStr = y + x;
top_back(vec);
top_back(vec);
return concatStr;
}
}
int main()
{
//...
auto ret = concat(some, stuff, here)
if(ret != "") // only print if ret actually holds a string
std::cout << ret;
//...
}
Because you are not satisfied with C++17 solutions, it is possible to write your own std::optional implementation.
template<typename T>
class Optional
{
bool m_HasValue;
T m_Object;
public:
Optional() : m_HasValue(false){};
Optional(T&& Object) : m_HasValue(true), m_Object(std::forward<T>(Object)){};
operator T&(){return m_Object;}
operator bool(){return m_HasValue;}
T& operator*(){return m_Object;}
};
This is a very simplified version of std::optional, but it will fulfill your needs.
Its usage remains the same as in this post above.
using std::string;
Optional<string> DoSomething(string Input)
{
if(Input == "dontprocessme")
return {}
// ... otherwise process the string
string Output;
// blah blah
return Output;
}
// ...
auto RetString = DoSomething("processme");
if(RetString)
std::cout << *RetString;
How can I simplify this Code?
mfer::i_value* make_empty_value(mfer::tag tag_)
{
if (tag_ == mfer::tag::mwf_ble) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_ble>());
} else if (tag_ == mfer::tag::mwf_chn) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_chn>());
} else if (tag_ == mfer::tag::mwf_blk) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_blk>());
} else if (tag_ == mfer::tag::mwf_seq) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_seq>());
} else if (tag_ == mfer::tag::mwf_man) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_man>());
} else if (tag_ == mfer::tag::mwf_ivl) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_ivl>());
} else if (tag_ == mfer::tag::mwf_sen) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_sen>());
} else if (tag_ == mfer::tag::mwf_wfm) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_wfm>());
} else if (tag_ == mfer::tag::mwf_pre) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_pre>());
} else if (tag_ == mfer::tag::mwf_off) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_off>());
} else if (tag_ == mfer::tag::mwf_nul) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_nul>());
} else if (tag_ == mfer::tag::mwf_pnt) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_pnt>());
} else if (tag_ == mfer::tag::mwf_nte) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_nte>());
} else if (tag_ == mfer::tag::mwf_txc) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_txc>());
} else if (tag_ == mfer::tag::mwf_flt) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_flt>());
} else if (tag_ == mfer::tag::mwf_skw) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_skw>());
} else if (tag_ == mfer::tag::mwf_mss) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_mss>());
} else if (tag_ == mfer::tag::mwf_pnm) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_pnm>());
} else if (tag_ == mfer::tag::mwf_pid) {
return memory_manager::instance().add(new mfer::t_value<mfer::tag::mwf_pid>());
}
return nullptr;
}
Briefly stating,
mfer::tag is enumeration, defined like enum tag {}; in namespace mfer.
mfer::i_value is abstract class.
class i_value {};
mfer::t_value is templated class like,
template <mfer::tag tag_type>
class t_value : public i_value {};
At this moment, I don't know how to simplify this make_empty_value().
Ideally, I want to make it like this:
mfer::i_value* make_empty_value(mfer::tag tag_)
{
return memory_manager::instance().add(new mfer::t_value<tag_>());
}
But I know that it is template, so above one doesn't make sense.
Is there any idea simplify this code? (Some modern C++ features, Boost libraries, and so on)
With a little template work, we can get the factory function down to:
i_value* make_empty_value(tag tag_type)
{
static constexpr auto factory = make_factory(all_tags());
auto index = std::size_t(tag_type - tag::first);
if (index < tag::ntags) {
return memory_manager::instance().add(factory[index]());
}
else {
return nullptr;
}
}
Full code below.
The i_value generator map is built at compile time, allowing constant-time lookup.
constraints:
the values in the enum must be consecutive, but they need not begin at zero.
this demo requires c++14. It can be easily adapted to work with c++11. For c++03 we'd want to reach out to boost mpl or boost_pp.
complete working example:
#include <array>
#include <utility>
#include <deque>
#include <iostream>
// minimal implementation of virtual base
class i_value {
public:
virtual void prove() const = 0;
virtual ~i_value() = default;
};
// tag enum - note that we have supplied some extra introspection information
// these could just as well be constexpr integers outside the enum
enum tag
{
ble,
chn,
blk,
seq,
first = ble, // first available tag
last = seq, // last available tag
ntags = last-first // number of tags
};
/// Function to offset an index sequence by the distance from
/// zero to the first available tag - in case the first tag is not zero
template<std::size_t...tags>
constexpr auto tag_offset(std::index_sequence<tags...>)
{
return std::index_sequence<(tags + tag::first)...>();
}
/// Function to compute an index sequence of all valid tags
constexpr auto all_tags()
{
return tag_offset(std::make_index_sequence<std::size_t(ntags)>());
}
/// Factory function to generate a derived class for a given tag
template <tag tag_type>
class t_value : public i_value {
void prove() const override { void(std::cout << "I have tag " << tag_type << std::endl); }
~t_value() { void(std::cout << "tag " << tag_type << " destroyed" << std::endl); }
};
template<tag tag_type>
i_value* make_instance()
{
return new t_value<tag_type>();
}
/// Function to generate a 'factory' - an array of factory functions, one for
/// each tag in the variadic template argument tags...
/// Note that the array is zero-based, the tags may not be. All we care about
/// here is the size of the list of tags (and their values)
///
template<std::size_t...tags>
constexpr auto make_factory(std::index_sequence<tags...>)
{
return std::array<i_value* (*)(), sizeof...(tags)>
{
&make_instance<static_cast<tag>(tags)>...
};
}
// minimal memory manager
struct memory_manager {
struct impl {
i_value* add(i_value* item) {
_ivalues.push_back(item);
return item;
};
~impl() {
for (auto i = _ivalues.rbegin() ; i != _ivalues.rend() ; ++i) {
delete *i;
}
}
std::deque<i_value*> _ivalues;
};
static impl& instance()
{
static impl _instance = {};
return _instance;
}
};
// here is resulting factory function.
i_value* make_empty_value(tag tag_type)
{
static constexpr auto factory = make_factory(all_tags());
auto index = std::size_t(tag_type - tag::first);
if (index < tag::ntags) {
return memory_manager::instance().add(factory[index]());
}
else {
return nullptr;
}
}
// test
int main()
{
for(auto tag_type : { tag::ble, tag::chn })
{
auto pvalue = make_empty_value(tag_type);
pvalue->prove();
}
}
expected output:
I have tag 0
I have tag 1
tag 1 destroyed
tag 0 destroyed
You can map the tags to a factory method;
typedef std::unordered_map<mfer::tag,std::function<mfer::i_value*()>> TagMap;
TagMap create_tag_map()
{
TagMap map;
map[mfer::tag::mwf_ble] = [](){ return new mfer::t_value<mfer::tag::mwf_ble>(); };
map[mfer::tag::mwf_chn] = [](){ return new mfer::t_value<mfer::tag::mwf_chn>(); };
map[mfer::tag::mwf_blk] = [](){ return new mfer::t_value<mfer::tag::mwf_blk>(); };
//...
return map;
}
The create_empty_value method could then look like this:
mfer::i_value* make_empty_value(mfer::tag tag_)
{
static TagMap factory = create_tag_map();
auto it = factory.find( tag_ );
if( it != factory.end() )
{
return memory_manager::instance().add( it->second() );
}
return nullptr;
}
see simplified version Live on Coliru
You can create a recursive template function if the enumerate value follows a known pattern (by default next enumerate value equals previous enumerate +1):
//anonymous namespace to "help innliner"
namespace{
//This function return the next enumerates value:
constexpr mref::tag next_tag(mref::tag tag_) {
return static_cast<mref::tag>(
static_cast<std::underlying_type_t<mref::tag>>(tag_) + 1);
}
//The compute function is wrapped in a structure to enable template
//specialization:
template <mref::tag Tag> struct add_to_mem_manager {
static mfer::i_value* compute(mref::tag tag_) {
if (Tag == tag_) {
return memory_manager::instance().add(
new mfer::t_value<Tag>());
} else {
return add_to_mem_manager<next_tag(Tag)>::compute(tag_);
}
}
};
//Specialization for last enumerate
template <> struct add_to_mem_manager<mfer::tag::mwf_pid> {
static mref::ivalue* compute(mref::tag tag_) {
assert(mref::tag::mwf_pid == tag_);
return memory_manager::instance().add(
new mfer::t_value<mfer::tag::mwf_pid>());
}
};
}
mfer::i_value* make_empty_value(mfer::tag tag_){
//call with template parameter equals to the
//the enumerate whose values is the smallest
return add_to_mem_manager<mfer::tag::mwf_ble>::compute(tag_);
}
If you don't know the constitutive rule of your enumerate, you cannot do this,( generaly constitutive law is as in this example, x[i+1]=x[i]+1, or x[i+1]=x[i]<<1 (left shift).) Otherwise their is no way to iterate over elements of an enumeration.
Note: The function compute will certainly be inlined, but in doubt you can use
compiler specific attribute as __forceinline with MSVC or __attribute__((__always_inline__)) with GCC or clang.
Not directly using your example, but you can do something on the below lines, i.e converting enum to a type.
enum Type {
Type_A,
Type_B,
};
template <Type T>
struct Enum2Type {
constexpr static const Type type = T;
};
template <typename T>
mfer::i_value* make_empty_value(T tag_type)
{
return memory_manager::instance().add(new mfer::t_value<tag_type.type>());
}
auto val = make_empty_value(Enum2Type<Type_A>());
auto val2 = make_empty_value(Enum2Type<Type_B>());
The only scope of simplification I see is in removing the boilerplate code by replacing with a fixed macro. This will be soothing to the viewer.
Instead of so many if-else if, make it a switch/case as below:
#define CASE(TAG) \
case TAG: return memory_manager::instance().add(new mfer::t_value<TAG>())
mfer::i_value* make_empty_value(const mfer::tag tag_)
{
switch(tag_) {
{
CASE(mfer::tag::mwf_ble);
CASE(mfer::tag::mwf_chn);
CASE(mfer::tag::mwf_blk);
//...
default: break;
}
return nullptr;
}
#undef CASE
I am wondering how to sort an array that contains objects of a custom class. I am trying to apply different sorting algorithms but in the swapping something goes wrong.
Here is my Code:
class RaceCar
{
private:
char* _brand;
char* _model;
double _price;
int _horse_power;
public:
//Other code
RaceCar(const RaceCar& rc):_price(rc._price), _horse_power(rc._horse_power)
{
_brand = new char[strlen(rc._brand)+1];
strcpy(_brand, rc._brand);
_model = new char[strlen(rc._model)+1];
strcpy(_model,rc._model);
}
RaceCar& operator=(const RaceCar& rc)
{
if(this != &rc)
{
delete _brand;
delete _model;
_brand = new char[strlen(rc._brand)+1];
strcpy(_brand, rc._brand);
_model = new char[strlen(rc._model)+1];
strcpy(_model, rc._model);
_price = rc._price;
_horse_power = rc._horse_power;
}
return *this;
}
bool operator<(const RaceCar& rc)
{
return (this->_price/this->_horse_power) > (rc._price/rc._horse_power);
}
//Other code
};
And this is the class that contains an array of RaceCars. I am trying to implement SortCars() method that orders the RaceCar objects inside the array of cars:
class RaceCarGarage
{
private:
RaceCar* _cars;
int _max_cars;
int _curr_occupied;
public:
RaceCarGarage():_cars(NULL), _max_cars(0),_curr_occupied(0){}
RaceCarGarage(const RaceCar& car, int max_cars)
:_max_cars(max_cars), _curr_occupied(0)
{
_cars = new RaceCar[_max_cars];
}
~RaceCarGarage()
{
delete _cars;
}
void AddCar(const RaceCar& car)
{
if(_curr_occupied < _max_cars)
{
_cars[_curr_occupied] = car;
_curr_occupied += 1;
}
}
void DisplayCars()
{
if(_curr_occupied > 0)
{
for(int i=0 ; i<_curr_occupied ; i++)
{
cout<<(i+1)<<". ";
(_cars+i)->Display();
}
}
}
void SortCars()
{
if(_curr_occupied > 1)
{
for(int i=0 ; i<_curr_occupied ; i++)
{
for(int j = i+1 ; j<_curr_occupied ; j++)
{
if(_cars[j]<_cars[i])
{
RaceCar buffer = _cars[i];
_cars[i] = _cars[j];
_cars[j] = buffer;
}
}
}
}
}
};
The problem with the swapping is that you use the traditional way to do:
temp = a // operator=
a = b // operator=
b = temp; // operator=
However, if you write:
RaceCar temp = a; // Copy constructor gets called (see comment on standard)
a = b; // operator=
b = temp; // operator=
The default copy constructor, just copies member by member, so just copies your pointer. So at the end, your temp and your will try to delete twice the same object pointed to.
Remark on assignment initializer :
For a type T, a statement in form T a = b; is an initializer.
The ISO standard C++ in section 12.6.1 point 1 explains "a single assignment-expression can be specified as an initializer using the = form of initialization. Either direct-initialization semantics or copy-initialization semantics apply;"