I'm writing a class which will be used to perform some calculations on a set of values, with scaling based on a per-value weight. The values and weights are supplied to the class' constructor. The class will be part of an internal library, and so I want to put as few restrictions as possible on the clients data structures - some clients will use vectors of structs or std::pairs, another separate OpenCV matrixes. During development I've taken start/end iterators and relied on the pair mechanism (val = it->first, weight = it->second).
How could this be done better, without too much hassle for the programmer on the other end? Generally, what is considered best practise when having this sort of multi-dimensional input?
Iterators are fine. However, relying on the types having public members called first and second is a pretty big restriction.
In C++0x, access to std::pair members will be unified with the access patterns of std::tuple, via a get function. This would allow you to overload and specialize the get function for arbitrary types:
#include <iostream>
#include <utility>
template <class T>
void print(const T& data)
{
using std::get;
std::cout << get<0>(data) << ' ' << get<1>(data) << '\n';
}
struct Coord
{
int x, y;
};
template <unsigned>
int get(const Coord&);
template <>
int get<0>(const Coord& c) { return c.x; }
template <>
int get<1>(const Coord& c) { return c.y; }
int main()
{
print(std::make_pair(1, 2));
Coord coord = {4, 5};
print(coord);
}
In case your standard library doesn't have get for pair, then boost's tuple library seems to have it.
That situation is pretty much what templates are in the language for.
Related
In the C++ standard library, there is std::vector, and you can specify the type you want to put into a vector while declaring it.
I want to create a class which would contain a vector of either strings, or ints, or whatever I would ever need. Is it possible to do this in an easy way, or would I have to write thousands of lines in C and assembly?
If you put the data type in the declaration, you can instantiate different kinds of vectors: vector<int> myint_v; vector<string> mystring_v; etc.... but I think your asking about how to make a Generic class and GeeksForGeeks has a really good article on this.
#include <iostream>
using namespace std;
template <typename T>
class Array {
private:
T* ptr;
int size;
public:
Array(T arr[], int s);
void print();
};
template <typename T>
Array<T>::Array(T arr[], int s)
{
ptr = new T[s];
size = s;
for (int i = 0; i < size; i++)
ptr[i] = arr[i];
}
template <typename T>
void Array<T>::print()
{
for (int i = 0; i < size; i++)
cout << " " << *(ptr + i);
cout << endl;
}
int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
Array<int> a(arr, 5);
a.print();
return 0;
}
That's just an example of using a template to declare a methods in a class. Hopefully that helps. Let me know.
C++ has variant and any. Variant supports a fixed list of alternative types; any supports any type of object that can be copied.
Now, any is really tricky to use right; in order to get back your data, you have to know what type of data (exactly) is in the any. And often variant is all you need.
If your goal is something akin to a json structure, well there are plenty of implementations of that.
Yes you can do via some sort of manipulation. Easiest method so far i have would be using std::pair<type1,type2> method. I will initiliaze with string and double which would be able to hold most of the things you need. String can hold single character to whole text and double pretty much same thing for the number.
Easiest way is,
vector<pair<type1,type2>> vector_name;
Then push each value via make_pair method
vector_name.push_back(make_pair(type1 Value, type2 Value));
When accessing it .first is for type1 and .second would be for type2. You can see more in the code below
#include <iostream>
#include <vector>
#include <utility>
#include <string>
using namespace std;
int main(){
vector<pair<string, double>> mypair;
mypair.push_back(make_pair("HelloWorld!", 8.2021));
mypair.push_back(make_pair("!", 8));
for(auto &&i:mypair){
cout << i.first << " " << i.second << "\n";
}
return 0;
}
I want to add a major difference. std::variant is a compile time feature where std::any is runtime.
Generally, what you want is std::any. Variant is a type safe union which somehow breaks what the original union was designed for (to overlook types at runtime as well).
The benefit of std::any is that your don't have to change often a type which can contain a std::any instead of constantly changing the data (and, for example, to recompile the entire precompilation headers). The drawback is that you have to ensure that it contains the type you want, or you get an exception when using std::any_cast. There is added overhead as well.
The final advice is to avoid using any of the two, unless there is a good reason. There are safer ways to use multiple types (polymorphism). As said, your can also put your data inside an object like json or XML.
As programming becomes more complex, and the need to perform operations on struct data becomes visible. Is there a conversion method for converting a struct type into an array of its members such that:
struct FooDesc Foo{
int num_Foo;
int num_Bar;
int GreenFoo;
};
can be represented by:
int Bar[2];
Or better, dynamically as:
vector<int> Bar;
The goal is to convert or re-represent the data struct as an iteratable form, without the excessive use of the assignment operator.
You could use unnamed structs to make a hybrid struct where its member could be treated as an array:
struct Foo {
union {
struct {
int x;
int y;
int z;
};
struct {
int array[3];
};
};
};
LIVE DEMO
Note however, that unnamed struct comes from C11 and its not a standard C++ feature. It is supported as an extension though by GCC as well Clang.
If your structs are POD then you might consider using std::tuple instead of structs. You could then use various template facilities to work through the members of the tuple.
Here is a simple example that prints the elements of a tuple - using boost::fusion::tuple instead of the std::tuple since it has many more tuple-manipulating facilities available:
#include <boost/fusion/tuple.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <iostream>
struct Printer {
template<typename T>
void operator()(const T &t) const {
std::cout << t << std::endl;
}
};
int main(int argc, const char * argv[])
{
boost::fusion::tuple<int, int, int, int, float> t =
boost::fusion::make_tuple(3, 5, 1, 9, 7.6f);
boost::fusion::for_each(t, Printer());
return 0;
}
You could include these in unions with the struct but you'd want to do some testing to ensure proper alignment agreement.
The upside is that these manipulations are very fast - most of the work is done at compile time. The down-side is that you can't use normal control structs like indexing with runtime indices - you'd have to build an abstraction layer around that as the normal get<i>(tuple) accessor requires that i be a compile time constant. Whether this is worth the complexity depends strongly on the application.
How about:
vector <Foo> Bar;
You can then add instances of your struct and then access each element as desired, using an array-like format.
See this related question for further information:
Vector of structs initialization
Upon re-reading your question a few times, I think I mis-understood your intent and answered the "wrong question". You can make an array of your struct as mentioned above and index it as an array, but I don't believe it is quite as simple as that to make each struct element a different element of an array. If you are looking to make an array of structs, my answer should help. If you are looking to make each element of your struct an element of your array, 40two's answer should help you out.
I wrote a small program of using std::map here as follows.
int main()
{
map<int,float>m1;
m1.insert(pair<int,float>(10,15.0)); //step-1
m1.insert(pair<float,int>(12.0,13)); //step-2
cout<<"map size="<<m1.size()<<endl; //step -3
I created a map with int type as key and float type as value(key-value) pair for the map m1
Created a normal int-float pair and inserted to map.
Created a cross float-int pair and inserted to map. Now I know that implicit conversion is making this pair to get inserted to map.
Here I just don't want the implicit conversion to take place and compiler error should be given.
What sort of changes I have to do in this program/map to make the comipiler flag an error while we try to do step-2 type operation?
Here's a suggestion:
template <typename K, typename V, typename W>
void map_insert(map<K,V>& m, K k, W w) {
V v = w;
m.insert(pair<K,V>(k,v));
}
int main() {
map<int,float>m1;
map_insert(m1, 10, 15.0);
map_insert(m1, 12.0, 13); // compiler complains here
cout<<"map size="<<m1.size()<<endl;
The third template parameter is a bit awkward but is necessary to allow casting from double to float.
This is not possible (and even if it is possible, then it would be major hack that you shouldn't use).
insert takes a value_type as argument, which is a pair<int const,float>.
So, when you try to insert a pair<float, int>, the compiler looks for a conversion, that is: a constructor of pair<int const, float> that takes a pair<float, int> as argument, which simply exists. In fact, I tried to come up with a partial specialization for that template member (that allows the conversion) which then you could have fail on the remaining template parameter, but I failed to do so; it seems not possible. Anyway, it would be a very dirty hack that you just shouldn't be doing just to avoid a typo. Elsewhere you might need this conversion, and it's a no no to define anything in namespace std anyway.
So what is the solution to "How can I avoid this kind of typos?" ?
Here is what I usually do:
1) All my maps have a typedef for their type.
2) I then use ::value_type (and ::iterator etc) on that type exclusively.
This is not only more robust, it is also more flexible: you can change the container type later on and the code is likely to still work.
So, your code would become:
int main()
{
typedef std::map<int,float> m_type;
m_type m1;
m1.insert(m_type::value_type(10,15.0)); // allowed
m1.insert(m_type::value_type(12.0,13)); // no risk for a typo.
An alternative solution would be to wrap your float in a custom class. This isn't a bad thing to do anyway for (again) reasons of flexibility. It is rarely nice to have written code using a std::map<int, builtin-type> to then realize you need to store more data, and believe me that happens a lot. You might as well start with a class from the beginning.
There may well be a simpler way but this is what occurred to me:
#include <iostream>
#include <map>
template<typename Key, typename Value>
struct typesafe_pair
{
const Key& key;
const Value& value;
explicit typesafe_pair(const Key& key, const Value& value): key(key), value(value) {}
operator typename std::map<Key, Value>::value_type() { return typename std::map<Key, Value>::value_type(key, value); }
};
int main()
{
std::map<int,float>m1;
m1.insert(std::pair<int,float>(10,15.0)); // allowed
m1.insert(std::pair<float,int>(12.0,13)); // allowed!!
m1.insert(typesafe_pair<int,float>(10, 15.0)); // allowed
m1.insert(typesafe_pair<float, int>(12.0, 13)); // compiler error
std::cout << "map size=" << m1.size() << std::endl; //step -3
}
EDIT: 1 Someone may be able to provide a better (more efficient) solution involving rvalue references and perfect forwarding magic that I don't quite grasp yet.
EDIT 2: I think Carlo Wood has the best solution IMHO.
I'm currently trying to do a complicated variable correction to a bunch of variables (based on normalizing in various phase spaces) for some data that I'm reading in. Since each correction follows the same process, I was wondering if there would be anyway to do this iteratively rather than handle each variable by itself (since I need to this for about 18-20 variables). Can C++ handle this? I was told by someone to try this in python but I feel like it could be done in C++ in some way... I'm just hitting a wall!
To give you an idea, given something like:
class VariableClass{
public :
//each object of this class represents an event for this particlular data set
//containing the following variables
double x;
double y;
double z;
}
I want to do something along the lines of:
for (int i=0; i < num_variables; i++)
{
for (int j=0; j < num_events; j++)
{
//iterate through events
}
//correct variable here, then move on to next one
}
Thanks in advance for any advice!!!
I'm assuming your member variables will not all have the same type. Otherwise you can just throw them into a container. If you have C++11, one way you could solve this problem is a tuple. With some template metaprogramming you can simulate a loop over all elements of the tuple. The function std::tie will build a tuple with references to all of your members that you can "iterate" like this:
struct DoCorrection
{
template<typename T>
void operator()(T& t) const { /* code goes here */ }
};
for_each(std::tie(x, y, z), DoCorrection());
// see linked SO answer for the detailed code to make this special for_each work.
Then, you can specialize operator() for each member variable type. That will let you do the appropriate math automatically without manually keeping track of the types.
taken from glm (detail vec3.incl)
template <typename T>
GLM_FUNC_QUALIFIER typename tvec3<T>::value_type &
tvec3<T>::operator[]
(
size_type i
)
{
assert(i < this->length());
return (&x)[i];
}
this would translate to your example:
class VariableClass{
public :
//each object of this class represents an event for this particlular data
double x;
double y;
double z;
double & operator[](int i) {
assert(i < 3);
return (&x)[i];
}
}
VariableClass foo();
foo.x = 2.0;
std::cout << foo[0] << std::endl; // => 2.0
Althought i would recomment glm, if it is just about vector math.
Yes, just put all your variables into a container, like std::vector, for example.
http://en.cppreference.com/w/cpp/container/vector
I recommend spending some time reading about all the std classes. There are many containers and many uses.
In general you cannot iterate over members without relying on implementation defined things like padding or reordering of sections with different access qualifiers (literally no compiler does the later - it is allowed though).
However, you can use a the generalization of a record type: a std::tuple. Iterating a tuple isn't straight-forward but you will find plenty of code that does it. The worst here is the loss of named variables, which you can mimic with members.
If you use Boost, you can use Boost.Fusion's helper-macro BOOST_FUSION_ADAPT_STRUCT to turn a struct into a Fusion sequence and then you can use it with Fusion algorithms.
From time to time I am feeling the need for a certain kind of iterator (for which I can't make up a good name except the one prefixed to the title of this question).
Suppose we have a function (or function object) that maps an integer to type T. That is, we have a definition of a mathematical sequence, but we don't actually have it stored in memory. I want to make an iterator out of it. The iterator class would look something like this:
template <class F, class T>
class sequence_iterator : public std::iterator<...>
{
int i;
F f;
public:
sequence_iterator (F f, int i = 0):f(f), i(i){}
//operators ==, ++, +, -, etc. will compare, increment, etc. the value of i.
T operator*() const
{
return f(i);
}
};
template <class T, class F>
sequence_iterator<F, T> make_sequence_iterator(F f, int i)
{
return sequence_iterator<F, T>(f, i);
}
Maybe I am being naive, but I personally feel that this iterator would be very useful. For example, suppose I have a function that checks whether a number is prime or not. And I want to count the number of primes in the interval [a,b]. I'd do this;
int identity(int i)
{
return i;
}
count_if(make_sequence_iterator<int>(identity, a), make_sequence_iterator<int>(identity, b), isPrime);
Since I have discovered something that would be useful (at least IMHO) I am definitely positive that it exists in boost or the standard library. I just can't find it. So, is there anything like this in boost?. In the very unlikely event that there actually isn't, then I am going to write one - and in this case I'd like to know your opinion whether or not should I make the iterator_category random_access_iterator_tag. My concern is that this isn't a real RAI, because operator* doesn't return a reference.
Thanks in advance for any help.
boost::counting_iterator and boost::transform_iterator should do the trick:
template <typename I, typename F>
boost::transform_iterator<
F,
boost::counting_iterator<I>>
make_sequence_iterator(I i, F f)
{
return boost::make_transform_iterator(
boost::counting_iterator<I>(i), f);
}
Usage:
std::copy(make_sequence_iterator(0, f), make_sequence_iterator(n, f), out);
I would call this an integer mapping iterator, since it maps a function over a subsequence of the integers. And no, I've never encountered this in Boost or in the STL. I'm not sure why that is, since your idea is very similar to the concept of stream iterators, which also generate elements by calling functions.
Whether you want random access iteration is up to you. I'd try building a forward or bidirectional iterator first, since (e.g.) repeated binary searches over a sequence of integers may be faster if they're generated and stored in one go.
Does the boost::transform_iterator fills your needs? there are several useful iterator adaptors in boost, the doc is here.
I think boost::counting_iterator is what you are looking for, or atleast comes the closest. Is there something you are looking for it doesn't provide? One could do, for example:
std::count_if(boost::counting_iterator<int>(0),
boost::counting_iterator<int>(10),
is_prime); // or whatever ...
In short, it is an iterator over a lazy sequence of consecutive values.
Boost.Utility contains a generator iterator adaptor. An example from the documentation:
#include <iostream>
#include <boost/generator_iterator.hpp>
class my_generator
{
public:
typedef int result_type;
my_generator() : state(0) { }
int operator()() { return ++state; }
private:
int state;
};
int main()
{
my_generator gen;
boost::generator_iterator_generator<my_generator>::type it =
boost::make_generator_iterator(gen);
for (int i = 0; i < 10; ++i, ++it)
std::cout << *it << std::endl;
}