C++ Initializer_List into Vector of Pointers - c++

I've been trying to streamline some of my code, condensing and making calls easier where I can. One of the things I've been trying to do is fuse two common overloads I have all over the place into one. They are as follows:
void MyClass::addSomething(Something & a)
{
vectorOfSomething.push_back(&a)
}
void MyClass::addSomething(std::vector<Something*> a)
{
for (unsigned int i = 0; i < a.size(); i++)
vectorOfSomething.push_back(a[i]);
}
The class Something is abstract. vectorOfSomething is a vector of pointers to Somethings.
Essentially, instead of having to do this:
std::Vector mySomethings = {&something1, &something2};
addSomething(mySomethings);
I want to do this:
addSomething({something1, something2});
So it is more similar to the first overload (no need for the user to create a vector of pointers first). Looking around the two ways I saw were either through: std::initializer_list or variadic templates, both of which I am not afraid to admit is completely foreign to me.
I've given it a shot with initializer lists but have run into a ton of errors trying various things. I've managed to get the function to actually accept the list, but I can't quite figure out how to get it to populate the vector correctly. The main issue seems to be that the init list has values that are 'const' within.
If anyone has any idea on how to make this work I would be grateful!

Something like this :
#include <iostream>
#include <initializer_list>
#include <vector>
#include <list>
struct MyClass {
template <typename It >
void Add( It b, It e ) {
data_.insert( end(data_), b, e );
}
void Add( std::initializer_list<int> const & elems ) {
Add( begin(elems), end(elems) );
}
template <typename T>
void Add( T const & cont ) {
Add( begin(cont), end(cont) );
}
std::vector<int> data_;
friend std::ostream & operator<<( std::ostream & os, MyClass const & mc ) {
for( auto & e : mc.data_ )
os << e << " ";
return os;
}
};
int main() {
MyClass foo;
foo.Add( { 1, 3 });
std::vector<int> v { 1,2};
foo.Add( v );
std::list<int> l { 4,5};
foo.Add( l );
std::cout << foo;
}
A compiler cannot infer a template argument to initializer_list, the specialization has to be explicit.

Related

Virtually turn vector of struct into vector of struct members

I have a function that takes a vector-like input. To simplify things, let's use this print_in_order function:
#include <iostream>
#include <vector>
template <typename vectorlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme) {
for (int i : order)
std::cout << printme[i] << std::endl;
}
int main() {
std::vector<int> printme = {100, 200, 300};
std::vector<int> order = {2,0,1};
print_in_order(order, printme);
}
Now I have a vector<Elem> and want to print a single integer member, Elem.a, for each Elem in the vector. I could do this by creating a new vector<int> (copying a for all Elems) and pass this to the print function - however, I feel like there must be a way to pass a "virtual" vector that, when operator[] is used on it, returns this only the member a. Note that I don't want to change the print_in_order function to access the member, it should remain general.
Is this possible, maybe with a lambda expression?
Full code below.
#include <iostream>
#include <vector>
struct Elem {
int a,b;
Elem(int a, int b) : a(a),b(b) {}
};
template <typename vectorlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme) {
for (int i : order)
std::cout << printme[i] << std::endl;
}
int main() {
std::vector<Elem> printme = {Elem(1,100), Elem(2,200), Elem(3,300)};
std::vector<int> order = {2,0,1};
// how to do this?
virtual_vector X(printme) // behaves like a std::vector<Elem.a>
print_in_order(order, X);
}
It's not really possible to directly do what you want. Instead you might want to take a hint from the standard algorithm library, for example std::for_each where you take an extra argument that is a function-like object that you call for each element. Then you could easily pass a lambda function that prints only the wanted element.
Perhaps something like
template<typename vectorlike, typename functionlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme,
functionlike func) {
for (int i : order)
func(printme[i]);
}
Then call it like
print_in_order(order, printme, [](Elem const& elem) {
std::cout << elem.a;
});
Since C++ have function overloading you can still keep the old print_in_order function for plain vectors.
Using member pointers you can implement a proxy type that will allow you view a container of objects by substituting each object by one of it's members (see pointer to data member) or by one of it's getters (see pointer to member function). The first solution addresses only data members, the second accounts for both.
The container will necessarily need to know which container to use and which member to map, which will be provided at construction. The type of a pointer to member depends on the type of that member so it will have to be considered as an additional template argument.
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
private:
const Container * m_container;
MemberPtr m_member;
};
Next, implement the operator[] operator, since you mentioned that it's how you wanted to access your elements. The syntax for dereferencing a member pointer can be surprising at first.
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
// Dispatch to the right get method
auto operator[](const size_t p_index) const
{
return (*m_container)[p_index].*m_member;
}
private:
const Container * m_container;
MemberPtr m_member;
};
To use this implementation, you would write something like this :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
virtual_vector<decltype(printme), decltype(&Elem::a)> X(printme, &Elem::a);
print_in_order(order, X);
}
This is a bit cumbersome since there is no template argument deduction happening. So lets add a free function to deduce the template arguments.
template<class Container, class MemberPtr>
virtual_vector<Container, MemberPtr>
make_virtual_vector(const Container & p_container, MemberPtr p_member_ptr)
{
return{ p_container, p_member_ptr };
}
The usage becomes :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
auto X = make_virtual_vector(printme, &Elem::a);
print_in_order(order, X);
}
If you want to support member functions, it's a little bit more complicated. First, the syntax to dereference a data member pointer is slightly different from calling a function member pointer. You have to implement two versions of the operator[] and enable the correct one based on the member pointer type. Luckily the standard provides std::enable_if and std::is_member_function_pointer (both in the <type_trait> header) which allow us to do just that. The member function pointer requires you to specify the arguments to pass to the function (non in this case) and an extra set of parentheses around the expression that would evaluate to the function to call (everything before the list of arguments).
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
// For mapping to a method
template<class T = MemberPtr>
auto operator[](std::enable_if_t<std::is_member_function_pointer<T>::value == true, const size_t> p_index) const
{
return ((*m_container)[p_index].*m_member)();
}
// For mapping to a member
template<class T = MemberPtr>
auto operator[](std::enable_if_t<std::is_member_function_pointer<T>::value == false, const size_t> p_index) const
{
return (*m_container)[p_index].*m_member;
}
private:
const Container * m_container;
MemberPtr m_member;
};
To test this, I've added a getter to the Elem class, for illustrative purposes.
struct Elem {
int a, b;
int foo() const { return a; }
Elem(int a, int b) : a(a), b(b) {}
};
And here is how it would be used :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
{ // print member
auto X = make_virtual_vector(printme, &Elem::a);
print_in_order(order, X);
}
{ // print method
auto X = make_virtual_vector(printme, &Elem::foo);
print_in_order(order, X);
}
}
You've got a choice of two data structures
struct Employee
{
std::string name;
double salary;
long payrollid;
};
std::vector<Employee> employees;
Or alternatively
struct Employees
{
std::vector<std::string> names;
std::vector<double> salaries;
std::vector<long> payrollids;
};
C++ is designed with the first option as the default. Other languages such as Javascript tend to encourage the second option.
If you want to find mean salary, option 2 is more convenient. If you want to sort the employees by salary, option 1 is easier to work with.
However you can use lamdas to partially interconvert between the two. The lambda is a trivial little function which takes an Employee and returns a salary for him - so effectively providing a flat vector of doubles we can take the mean of - or takes an index and an Employees and returns an employee, doing a little bit of trivial data reformatting.
template<class F>
struct index_fake_t{
F f;
decltype(auto) operator[](std::size_t i)const{
return f(i);
}
};
template<class F>
index_fake_t<F> index_fake( F f ){
return{std::move(f)};
}
template<class F>
auto reindexer(F f){
return [f=std::move(f)](auto&& v)mutable{
return index_fake([f=std::move(f),&v](auto i)->decltype(auto){
return v[f(i)];
});
};
}
template<class F>
auto indexer_mapper(F f){
return [f=std::move(f)](auto&& v)mutable{
return index_fake([f=std::move(f),&v](auto i)->decltype(auto){
return f(v[i]);
});
};
}
Now, print in order can be rewritten as:
template <typename vectorlike>
void print(vectorlike const & printme) {
for (auto&& x:printme)
std::cout << x << std::endl;
}
template <typename vectorlike>
void print_in_order(std::vector<int> const& reorder, vectorlike const & printme) {
print(reindexer([&](auto i){return reorder[i];})(printme));
}
and printing .a as:
print_in_order( reorder, indexer_mapper([](auto&&x){return x.a;})(printme) );
there may be some typos.

c++ auto-comparator for structs

There is many primitive structs (several hundreds), that are used to transfer data between two components (for example a player and a server). There are no methods in them, just raw data.
The task is to write all requests and answers to be able to replay a player scenario without a server (we remember all question and all answers, that are pure functions).
So the task is put this structs in map without comparator. Now we use memcmp, it allows not to think about changes in this structs and it is compact, but there are too many problems with padding and etc.
Is it possible to get smth like getHashValue or any default comparator with metaprogramming in c++?
Conditions:
1) I do not want to create a comparator for each struct.
2) I want to have an error if a field was added or deleted if it breaks existing behavior and needs fix.
3) I don't want to change header files with struct definitions.
Example of a struct
struct A {
int a;
int b;
c c;
}
bool operator<(const A& a1, const A& a2)
{
if (a1.a != a2.a) return a1.a < a2.a;
if (a1.b != a2.b) return a1.b < a2.b;
if (a1.c != a2.c) return a1.c < a2.c;
return false;
}
I can consider other languages to implement this exact part (collect questions/answers), if it will not require to describe all this structs on that language again.
In C++17 you can pull this off if you are willing to (A) hard code how many elements are in each struct somewhere, and (B) write or generate code for each count of number of elements in the struct.
template<std::size_t N>
using size_k = std::integral_constant<std::size_t, N>;
template<class T>
auto auto_tie( size_k<0>, T&& t ) {
return std::tie();
}
template<class T>
auto auto_tie( size_k<1>, T&& t ) {
auto& [ x0 ] = std::forward<T>(t);
return std::tie( x0 );
}
template<class T>
auto auto_tie( size_k<2>, T&& t ) {
auto& [ x0, x1 ] = std::forward<T>(t);
return std::tie( x0, x1 );
}
// etc
now, in the namespace of the struct in question, write
struct foo {
int x;
};
struct bar {
int a, b;
};
size_k<1> elems( foo const& ) { return {}; }
size_k<2> elems( bar const& ) { return {}; }
an elems function that return the size_k counting how many elements.
Now in the namespace of the structs, write:
template<class T, class Size=decltype(elems(std::declval<T const&>()))>
bool operator<( T const& lhs, T const& rhs ) {
return auto_tie( Size{}, lhs ) < auto_tie( Size{}, rhs );
}
and you are done.
Test code:
foo f0{1}, f1{2};
bar b0{1,2}, b1{-7, -3};
std::cout << (f0<f1) << (f1<f0) << (f0<f0) << "\n";
std::cout << (b0<b1) << (b1<b0) << (b0<b0) << "\n";
Live example.
Getting further than this will require writing 3rd party tools or waiting for reflection extension to C++, maybe in C++20 or 23.
If you get elems wrong, I believe the structured bindings code in auto_tie should generate an error.
I suppose you could write your own compare operator based upon memcmp.
bool operator<(const A &lhs, const A &rhs) {
return memcmp(&lhs, &rhs, sizeof(A)) < 0;
}
Off course, writing these for each object might be a burden, so you could write a template for this. Though without some SFINAE it will cover too much types.
#include <type_traits>
#include <cstring>
template<typename T>
std::enable_if_t<std::is_pod_v<std::decay_t<T> //< Check if POD
&& !std::is_fundamental_v<std::decay_t<T>>>, //< Don't override for fundamental types like 'int'
bool>
operator<(const T &lhs, const T &rhs) {
return memcmp(&lhs, &rhs, sizeof(std::decay_t<T>)) < 0;
}
EDIT: Note that this technique requires you to zero-initialize the structs.
Looks like the best way to do it is to write a generator, that will generate .h and .cpp with bool operator< for all types in this header file. Then add this project as pre-build step to the main.
It doesn't look like a nice solution, but it allows to avoid hand-written code duplication and will support adding/removing new structs/fields. So I didn't find a better way.

Sorting just two elements using STL

Quite often I have two variables foo1 and foo2 which are numeric types. They represent the bounds of something.
A user supplies values for them, but like a recalcitrant musician, not necessarily in the correct order!
So my code is littered with code like
if (foo2 < foo1){
std::swap(foo2, foo1);
}
Of course, this is an idiomatic sort with two elements not necessarily contiguous in memory. Which makes me wonder: is there a STL one-liner for this?
I suggest to take a step back and let the type system do the job for you: introduce a type like Bounds (or Interval) which takes care of the issue. Something like
template <typename T>
class Interval {
public:
Interval( T start, T end ) : m_start( start ), m_end( end ) {
if ( m_start > m_end ) {
std::swap( m_start, m_end );
}
}
const T &start() const { return m_start; }
const T &end() const { return m_end; }
private:
T m_start, m_end;
};
This not only centralizes the swap-to-sort code, it also helps asserting the correct order very early on so that you don't pass around two elements all the time, which means that you don't even need to check the order so often in the first place.
An alternative approach to avoid the issue is to express the boundaries as a pair of 'start value' and 'length' where the 'length' is an unsigned value.
No, but when you notice you wrote the same code twice it's time to write a function for it:
template<typename T, typename P = std::less<T>>
void swap_if(T& a, T& b, P p = P()) {
if (p(a, b)) {
using std::swap;
swap(a, b);
}
}
 
std::minmax returns pair of smallest and largest element. Which you can use with std::tie.
#include <algorithm>
#include <tuple>
#include <iostream>
int main()
{
int a = 7;
int b = 5;
std::tie(a, b) = std::minmax({a,b});
std::cout << a << " " << b; // output: 5 7
}
Note that this isn't the same as the if(a < b) std::swap(a,b); version. For example this doesn't work with move-only elements.
if the data type of your value that you're going to compare is not already in c++. You need to overload the comparison operators.
For example, if you want to compare foo1 and foo2
template <class T>
class Foo {
private:
int value; // value
public:
int GetValue() const {
return value;
}
};
bool operator<(const Foo& lhs, const Foo& rhs) {
return (lhs.GetValue() < rhs.GetValue());
}
If your value is some type of int, or double. Then you can use the std::list<>::sort member function.
For example:
std::list<int> integer_list;
int_list.push_back(1);
int_list.push_back(8);
int_list.push_back(9);
int_list.push_back(7);
int_list.sort();
for(std::list<int>::iterator list_iter = int_list.begin(); list_iter != int_list.end(); list_iter++)
{
std::cout<<*list_iter<<endl;
}

C++ Generic code for deleting pointer value in Map and vector of pointers

I have some generic code for deleting pointers within a vector or a value of a Map.
Is there a better way of doing this (without using shared_ptrs or any o fthe tr1 extensions )?
Also is the code correct?
Here is my code:
I have a namespace
#ifndef CONTAINERDELETE_H
#define CONTAINERDELETE_H
#include <functional>
#include <map>
#include <vector>
#include <algorithm>
namspace ContainerDelete{
template<class A, class B>
struct DeleteMap
{
bool operator()( pair<A,B> &x) const
{
delete x.second;
return true;
}
};
template<class T>
struct DeleteVector
{
bool operator()(T &x) const
{
delete x;
return true;
}
};
}
#endif
I would then use this namespace in some bit of code to delete a map or vector.
Test Map deletion.
#include "ContainerDelete.h"
using namespace std;
// Test function.
void TestMapDeletion()
{
// Add 10 string to map.
map<int,B*> testMap;
for( int Idx = 0; Idx < 10; ++Idx )
{
testMap[Idx] = new B();
}
// Now delete the map in a single line.
for_each( testMap.begin(),
testMap.end(),
ContainerDelete::DeleteMap<int,B*>());
}
Test Vector Deletion
// Test Function.
void TestVectorDeletion()
{
// Add 10 string to vector.
vector<B*> testVector;
for( int Index = 0; Index < 10; ++Index )
{
testVector.push_back( new B());
}
// Now delete the vector in a single line.
for_each( testVector.begin(),
testVector.end(),
ContainerDelete::DeleteVector<B*>());
}
Thanks,
Mike
Better would be if reduce the genericity as:
struct DeleteVector
{
template<class T> //use the template here!
void operator()(T &x) const
{
delete x;
}
};
if you do so, then you could simply write this:
for_each(testVector.begin(),
testVector.end(),
ContainerDelete::DeleteVector());
No need to pass type argument when you use DeleteVector, for it is not a class template anymore!
Similarly, you can implement DeleteMap functor.
You should also rename DeleteVector to DeleteT, and DeleteMap to DeletePairSecond, as both of these can be used more generically. For example, DeleteT can be used even with std::list, or even with arrays.
The code is ok. I can't imagine any other ways to delete the pointers. All you can do is to reduce explicit type specification like in upper question. I know one more uglier way to do it: functions deduce types of their template parameters. So you can write template function with the first argument - vector, second - ptr and then use std::bind of vector parameter to make this function accepting one parameter - ptr.
But functor is better and more flexible.

std::map of member function pointers?

I need to implement an std::map with <std::string, fn_ptr> pairs. The function pointers are pointers to methods of the same class that owns the map. The idea is to have direct access to the methods instead of implementing a switch or an equivalent.
( I am using std::string as keys for the map )
I'm quite new to C++, so could anyone post some pseudo-code or link that talks about implementing a map with function pointers? ( pointers to methods owned by the same class that owns the map )
If you think there's a better approach to my problem, suggestions are also welcome.
This is about the simplest I can come up with. Note no error checking, and the map could probably usefully be made static.
#include <map>
#include <iostream>
#include <string>
using namespace std;
struct A {
typedef int (A::*MFP)(int);
std::map <string, MFP> fmap;
int f( int x ) { return x + 1; }
int g( int x ) { return x + 2; }
A() {
fmap.insert( std::make_pair( "f", &A::f ));
fmap.insert( std::make_pair( "g", &A::g ));
}
int Call( const string & s, int x ) {
MFP fp = fmap[s];
return (this->*fp)(x);
}
};
int main() {
A a;
cout << a.Call( "f", 0 ) << endl;
cout << a.Call( "g", 0 ) << endl;
}
A template implementation could look like:
class Factory {
public:
enum which {
foo, bar, baz
};
template<which w>
A* newA(...);
...
};
template<Factory::which w>
A* Factory::newA(...) {
/* default implementation */
throw invalid_argument();
}
template<>
A* Factory::newA<Factory::foo>(...) {
/* specialization for a 'foo' style A */
...
}
....
This requires that the value used to determine which newA is called be known at compile time. You could potentially use a const char * as the template parameter, but it's not guaranteed to work on all compilers.
Yet another option is to create helper factories, one for each factory creation method, and store those in the map. This isn't a huge advantage over storing method pointers, but does let you define a default creation method and simplifies fetching things from the map (there's no need to check that the key exists, because you'll get a default factory). On the downside, an entry for each unknown key would be added to the map.
Also, if you use an enum rather than a string for the key type, you shouldn't need to worry about checking whether a key exists in the map. While it's possible for someone to pass an invalid enum key to newA, they'd have to explicitly cast the argument, which means they're not going to do it by accident. I'm having a hard time imagining a case where someone would purposefully cause a crash in newA; the potential scenarios involve security, but an application programmer could crash the app without using your class.
Since C++14, we can use a generic lambda to get rid easily of pointers to member methods.
It follows a minimal, working example of a forward function made up with a generic lambda function:
#include<utility>
#include<map>
#include<string>
#include<iostream>
struct SomeClass { };
struct SomeOtherClass { };
struct Test {
void test(SomeClass) { std::cout << "SomeClass" << std::endl; }
void test(SomeOtherClass) { std::cout << "SomeOtherClass" << std::endl; }
};
int main() {
Test test;
auto l = [&test](auto c){ test.test(c); };
std::map<std::string, decltype(l)> m;
m.emplace("foo", l);
m.emplace("bar", l);
m.at("foo")(SomeClass{});
m.at("bar")(SomeOtherClass{});
}
Another option is to use delegates as oppose to function pointers. This delegate implementation is pretty fast, supports polymorphisms, and plays well with stl containers.
You could have something like:
class MyClass {
public:
// defines
typedef fastdelegate::FastDelegate2<int, int, int> MyDelegate;
typedef std::map<std::string, MyDelegate> MyMap;
// populate your map of delegates
MyClass() {
_myMap["plus"] = fastdelegate::MakeDelegate(this, &Plus);
_myMap["minus"] = fastdelegate::MakeDelegate(this, &Minus);
}
bool Do(const std::string& operation, int a, int b, int& res){
MyMap::const_iterator it = _myMap.find(operation);
if (it != _myMap.end()){
res = it.second(a,b);
return true;
}
return false;
}
private:
int Plus (int a, int b) { return a+b; }
int Minus(int a, int b) { return a-b; }
MyMap _myMap;
};