Avoid using container to call a list of functions? - c++

I have a list of functions that return bools. I want to iterate through the list of functions and write a message for each one "Test 1 passed", "Test 2 failed" etc.
My current solution is to create a vector of function pointers, push back each function and then loop through the vector. Code below. Is there a way to avoid the container without repeating the generic message (pass/fail) code for each test (imagine there would be hundreds of tests). It feels as if the vector is unnecessary or that there must be a more elegant solution for this.
typedef bool (*Tests)();
std::vector<Tests> tests;
tests.push_back(FASTA_FILE_READER_TEST);
tests.push_back(EXACT_MATCH_TEST);
for (int i = 0; i < tests.size(); i++) {
std::cout << "Test " << i + 1
<< (tests[i]() ? " PASSED" : " FAILED")
<< std::endl;
}

Is there anything stopping you using an array?
#include <iostream>
bool FASTA_FILE_READER_TEST() { return false; }
bool EXACT_MATCH_TEST() { return false; }
int main()
{
typedef bool (*Tests)();
Tests tests[] = {FASTA_FILE_READER_TEST, EXACT_MATCH_TEST};
for (int i = 0; i < sizeof(tests)/sizeof(Tests); i++) {
std::cout << "Test " << i + 1
<< (tests[i]() ? " PASSED" : " FAILED")
<< std::endl;
}
}

You could use a function to do that:
template<typename Functor>
void test(Functor& functor){
static int i = 0;
bool ret = functor();
if(ret){
std::cout << "Test " << i++ << " passed" << std::endl;
} else {
std::cout << "Test " << i++ << " failed" << std::endl;
}
}
void main(){
test(FASTA_FILE_READER_TEST);
test(EXACT_MATCH_TEST);
}

If you can use C++11 features:
#include <array>
#include <iterator>
#include <algorithm>
#include <iostream>
typedef bool (*Test)();
std::array<Test, 2> tests {{ FASTA_FILE_READER_TEST, EXACT_MATCH_TEST }};
void TestAll()
{
size_t i = 1;
std::for_each(std::begin(tests), std::end(tests),
[&i](Test& t)
{
std::cout << "Test " << i++ << (t() ? " PASSED" : " FAILED") << std::endl;
});
}
Demo.
It's another way of doing what you've already got (and your way is just fine, IMO). If the extra capacity a vector might have set aside bothers you, you can call shrink_to_fit() on it when you're done pushing back.

Create a class for each test. Then one static instance of each class.
Contructors of classes runs tests.
This of course may cause problems, because tests are executed before main() function is called.

Related

What am I iterating in this find_if function?

Here is my code:
bool isNotValid (char a) {
if (isalpha(a) || a == '_')
{
cout << "\n- isalpha";
return 0;
}
else
{
cout << "\n- notalpha";
return 1;
}
}
bool test123(const string& test)
{
return find_if(test.begin(), test.end(), isNotValid) != test.end();
}
int main()
{
string test;
cout << "Test input: ";
cin >> test;
if (!test123(test))
cout << "\n- Valid\n";
else
cout << "\n- Not Valid\n";
return 0;
}
This is part of my code to check the validity of username in my program. I don't really understand what exactly I am iterating through when I insert the string into my function as address of the string. CPP reference states that find_if iterates from first to last position of a sequence.
Poked through the code with cout at different location, still didn't quite catch what is going on.
You are iterating your string. You did not pass the address of the string. The function takes the string as a reference to const, meaning it passes the actual string (no copy is made) and the function is not allowed to modify the string. You are iterating character by character in your string and calling your function isNotValid() on each character.
Notes:
Instead of returning 1 or 0 from isNotValid(), return true or false.
Consider flipping your logic and renaming the function to isValid() instead. You would also have to change test123() to use std::find_if_not(). Finally, you would check if the returned iterator is end() and not if it's not.
But, if you do change isNotValid() to isValid(), you'd be better off switching from std::find_if() entirely to to std::all_of(). It makes more sense, is more readable, and returns a bool directly (No need to compare against end()).
But if you want to keep your function isNotValid(), the comment that suggests using std::any_of() is what I would recommend for the same reasons.
Here's my take on your code:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
bool isValid(char a) {
return std::isalpha(static_cast<unsigned char>(a)) || a == '_'; // !
}
bool test123(const std::string& test) {
return std::all_of(test.begin(), test.end(), isValid); // !
}
int main() {
std::string testOne{"i_am_valid"};
std::string testTwo{"i_am_invalid_123"};
std::cout << "Testing: " << testOne << " : " << std::boolalpha
<< test123(testOne) << '\n';
std::cout << "Testing: " << testTwo << " : " << std::boolalpha
<< test123(testTwo) << '\n';
}
Output:
❯ ./a.out
Testing: i_am_valid : true
Testing: i_am_invalid_123 : false
I would argue that readability has stayed largely the same, but the mental load has been shifted; the Boolean flips make a bit more sense.
As you progress in your learning, you might not even want to have the function isValid() if it's a one-off thing. C++11 introduced lambdas, or functions as objects. C++20 also introduced ranges, so you don't have to pass a pair of iterators if you intend to iterate the whole container anyway.
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
bool test123(const std::string& test) {
return std::ranges::all_of(test, [](const auto& c) {
return std::isalpha(static_cast<unsigned char>(c)) || c == '_';
}); // !
}
int main() {
std::string testOne{"i_am_valid"};
std::string testTwo{"i_am_invalid_123"};
std::cout << "Testing: " << testOne << " : " << std::boolalpha
<< test123(testOne) << '\n';
std::cout << "Testing: " << testTwo << " : " << std::boolalpha
<< test123(testTwo) << '\n';
}
That's a bit hairy to read if you're not familiar with lambdas, but I find lambdas useful for checks like this where you're just doing it the one time.

Container initialization in C++98

I have to construct an ordered container (which must be iterable) with the following rule:
If the condition is true, the container is {1,0}, else it's {0,1}
I have the following code, but I don't find it "elegant":
vector<int> orderedSides;
if (condition)
{
orderedSides.push_back(1);
orderedSides.push_back(0);
}
else
{
orderedSides.push_back(0);
orderedSides.push_back(1);
}
Is there a better way to do this (from concision and performance point of view)?
You might implement something like this:
vector<int> orderedSides(2, 0);
(condition ? orderedSides.front() : orderedSides.back()) = 1;
which is a little bit shorter than explicit if clauses.
As #Deduplicator mentioned below, we might rewrite the second line in a more concise way:
orderedSides[!condition] = 1;
vector<int> orderedSides;
orderedSides.push_back(condition ? 1 : 0);
orderedSides.push_back(condition ? 0 : 1);
I don't think it's more performant but I find it more elegant.
You could compromise between efficiency and avoiding repetition, initialise the first with the condition and the second from the first.
vector<int> orderedSides(1, bool(condition)) ;
orderedSides.push_back(!orderedSides.back());
orderedSides.push_back(0);
orderedSides.push_back(1);
if (condition)
std::iter_swap(orderedSides.begin(), orderedSides.begin()+1);
I know this take bits cost. As one of candidates.
If building the elements (the ints in your question, whatever it is in real life) is free and side-effect-less:
static const int data[] = { 0, 1, 0 };
std::vector<int> orderedSides (data+condition, data+condition+2);
Full program example:
#include <iostream>
#include <vector>
std::vector<int> make(bool cond)
{
static const int data[] = { 0, 1, 0 };
return std::vector<int> (data+cond, data+cond+2);
}
std::ostream& operator<<(std::ostream& os, const std::vector<int>& v)
{
return os << "{ " << v[0] << ", " << v[1] << " }";
}
int main()
{
std::cout << "true: " << make(true) << "\n"
<< "false: " << make(false) << "\n";
}
Prints:
true: { 1, 0 }
false: { 0, 1 }
Demo
You can populate a std::vector from an array, even in C++98.
Here's an example:
#include <iostream>
#include <vector>
int main() {
bool condition = false;
std::cout << "condition is: " << std::boolalpha << condition << '\n';
int arr[][2] = {{0,1}, {1,0}};
int index = condition;
std::vector<int> v(arr[index], arr[index]+2);
for (int i = 0; i < v.size(); i++)
std::cout << v[i] << ' ';
std::cout << '\n';
}
The output is:
$ g++ tt.cc && ./a.out
condition is: false
0 1
For reference:
http://en.cppreference.com/w/cpp/container/vector/vector

Faking constness when method is const from the outside (example: caching)

Consider the following example:
#include <iostream>
using std::endl;
using std::cout;
class my_class {
private:
int _expensive_count_operation() const {
return 10;
}
bool cached;
int last_count;
public:
my_class() { cached = false; }
int get_count() {
if (cached) {
cout << "Got count from cache." << endl;
return last_count;
}
cout << "Computing count." << endl;
last_count = _expensive_count_operation();
cached = true;
return last_count;
}
int get_const_count() const {
my_class* _this = const_cast<my_class*>(this);
if (cached) {
cout << "Got count from cache." << endl;
return last_count;
}
cout << "Computing count." << endl;
_this->last_count = _expensive_count_operation();
_this->cached = true;
return last_count;
}
};
int main() {
my_class my_object1,my_object2;
int count;
count = my_object1.get_count();
cout << "Count: " << count << endl;
count = my_object1.get_count();
cout << "Count: " << count << endl;
count = my_object2.get_const_count();
cout << "Count: " << count << endl;
count = my_object2.get_const_count();
cout << "Count: " << count << endl;
}
The use of const_cast in the get_const_count method allows you to keep the method const. Now the question is what are the dangers associated with this? And how do they compare to the dangers associated with loosing the ability to use const instances (or pointers to them) of this class? And, even better, is there a better approach?
I often find myself in this situation where I have written code that I then want to optimize using caching. The problem is that I then have to remove the const declarations and propagate that change through the rest of the code base.
I would prefer to mark all cache related attributes as mutable. The meaning of const should be that the observable state is not affected by those methods (which is what your cache should do anyway). Keep in mind that all const-methods should also be thread-safe.
For further information I recommend the blog of Herb Sutter - he wrote some stuff about const-correctness since c++11. Here is also a direct Link to a related video from Herb.
It is ONLY valid to use const_cast to remove const if the original object was NOT const. If that is always the case, it should be no problem to do this.
Although I would prefer to set last_count and cached to mutable... Because you don't really want to accidentally modify any of the other parts of the object - but you DO want to modify those in the const member function.

How to make thread safe Log class that supports `<<` operations?

So I have such log class:
#include <iostream>
#include <sstream>
#include <boost/circular_buffer.hpp>
#include <boost/foreach.hpp>
class FlushInternal;
class Log
{
public:
static FlushInternal* endl;
Log(int log_length)
{
i = 0;
messages_buffer = new boost::circular_buffer<std::string>(log_length);
}
template <class T>
Log &operator<<(const T &v)
{
current_message << v;
return *this;
}
Log &operator<<(std::ostream&(*f)(std::ostream&))
{
current_message << *f;
return *this;
}
Log &operator<<(FlushInternal*)
{
++i;
messages_buffer->push_back(current_message.str());
clean_stringstream(current_message);
is_filled();
return *this;
}
boost::circular_buffer<std::string> *messages_buffer;
private:
int i;
std::stringstream current_message;
void is_filled()
{
if (i >= messages_buffer->capacity())
{
i = 0;
BOOST_FOREACH(std::string s, *messages_buffer)
{
std::cout << ++i << ": " << s << " ;" << std::endl;
}
i = 0;
}
}
void clean_stringstream(std::stringstream &message)
{
message.flush();
message.clear();
message.seekp(0);
message.str("");
}
};
FlushInternal* Log::endl = 0;
And I can Use it like this:
#include <log.h>
int main()
{
Log l(2);
l << "message one: " << 1 << Log::endl;
l << "message two:" << " " << 2 << Log::endl;
l << "message " << "three: " << 3 << Log::endl;
l << "message" << " " << "four: " << 4 << Log::endl;
std::cin.get();
}
This would output:
1: message one: 1 ;
2: message two: 2 ;
1: message three: 3 ;
2: message four: 4 ;
As you can see I can have as many << as I want inside each log message. I want to be capable to use one instance of Log class from many threads at the same time. So I would have something like (pseudocode that compiles, runs but traces nothing.):
#include <boost/thread.hpp>
#include <log.h>
Log *l;
void fun_one()
{
*l << "message one: " << 1 << Log::endl;
*l << "message two:" << " " << 2 << Log::endl;
}
void fun_two()
{
*l << "message " << "three: " << 3 << Log::endl;
*l << "message" << " " << "four: " << 4 << Log::endl;
}
int main()
{
l = new Log(2);
boost::thread(fun_one);
boost::thread(fun_two);
std::cin.get();
}
So as you can see I want messages to be inserted into log in multythreaded function. Lo I wonder - how to make my log cclass support this?
The approach linked by trojanfoe is pretty much the canonical one. Basically create some temporary thing for the leftmost << operator, accumulate everything, and output the message in the destructor for the temporary thing.
The only question is the exact mechanics of this accumulator. The example used ostringstream, but I've seen the ofstream for the log file used directly as well (requires locking to ensure the output ends up on one line).
Creating ostringstreams is relatively expensive on some platforms, because they may need to lock and copy some internal locale related things. You could re-implement also the << operator for interesting types, but I'd test the ostringstream approach first.
A useful optimization is determine at the point of the construction of the temporary whether the trace will be emitted (e.g., whether tracing is enabled at that particular level), and not create the guts of the temporary at all in that case - all the insertion operations will be no-ops.
Here's one approach:
http://drdobbs.com/cpp/201804215
It basically creates a new ostringstream object each time you perform logging, which makes it thread safe. I can't say I'm that keen on that, as it seems a little clumsy to me.
You might have a look at the Qt logging classes as they support the << operator, however I'm not sure about thread safety.

C++ STL map with custom comparator storing null pointers

I'm trying to write a copy constructor for an object managing a STL map containing pointers, where the key is a string. However, when I attempt to insert new values in the map, the pointers are set to NULL:
// ...
for(std::map<std::string, data_base*, order>::const_iterator it = other.elements.begin();
it != other.elements.end(); ++it){
data_base *t = it->second->clone();
std::cout << "CLONE: " << std::hex << t << std::endl;
elements[it->first] = t;
std::cout << "INSERTED: " << std::hex << elements[it->first] << std::endl;
}
// ...
other is the object being copied and elements the map. The clone() method returns a pointer to a new object (via new).
Running the code above I get something like:
CLONE: 0xcfbbc0
INSERTED: 0
I'm not a very experienced programmer and this issue is probably simple to fix, but I didnt find any solution to it searching around.
Thanks a lot for your time.
I don't see any problem with this code, other than maybe
std::map<std::string, data_base*, order>::const_iterator it
Here order gives the key comparator to use to sort the pairs contained in the map (often implemented as a tree).
Maybe you're doing something wrong in it, making your [] operator don't find the right ke, making your last line logging a new pair with a null ptr.
First, try without that order, using the default key-comparator (std::less), then if it don't work, post your order definition and the map declaration. If it's not enough, just provide a simple complete program that reproduce the problem.
I just wrote a simple similar test, using the default key-comparator :
#include <map>
#include <string>
#include <iostream>
struct Data
{
int k;
Data* clone() { return new Data(); }
};
typedef std::map< std::string, Data* > DataMap;
DataMap data_map;
int main()
{
data_map[ "hello" ] = new Data();
data_map[ "world" ] = new Data();
DataMap other_map;
for( DataMap::const_iterator it = data_map.begin(); it != data_map.end(); ++it)
{
Data*t = it->second->clone();
std::cout << "CLONE: " << std::hex << t << std::endl;
other_map[it->first] = t;
std::cout << "INSERTED: " << std::hex << other_map[it->first] << std::endl;
}
std::cin.ignore();
return 0;
}
On VS2010SP1, this outputs :
CLONE: 00034DD0
INSERTED: 00034DD0
CLONE: 00035098
INSERTED: 00035098
So it should be the problem, or maybe you're doing something wrong before.
Try this out, to help debug the issue. I'd recommend double-checking that the order function is correct. You can remove it to use std::less<T>, which is known to work.
// ...
typedef std::map<std::string, data_base*, order> string_db_map;
for(string_db_map::const_iterator it = other.elements.begin();
it != other.elements.end();
++it)
{
data_base *t = it->second->clone();
std::cout << "CLONE: " << std::hex << t << std::endl;
std::pair<string_db_map::iterator, bool) result = elements.insert(
string_db_map::value_type( it->first, t));
if ( !result.second )
{
std::cout << "element['" << it->first << "'] was already present, and replaced." << std::endl;
}
std::coud << "INSERTED [iterator]: " << std::hex << (*result.first).second << std::endl;
std::cout << "INSERTED [indexed]: " << std::hex << elements[it->first] << std::endl;
}
// ...