Writing a struct template with two vectors - c++

What I am trying to achieve is create a template of a struct myVector which would contain two vectors i.e. vector_a and vector_b. But i am quite new to templates. I mean, I know why and when one would prefer using Templates in certain situations but I am not quite sure how to tackle this problem. What I have written is:
'''
#include<iostream>
#include<stddef.h>
#include<vector>
template <typename T> struct myVector {
std::vector<T> vector_a;
std::vector<T> vector_b;
};
int main() {
myVector<int> z1(5);
myVector<int> z2(6);
}
'''
I end up getting errors like no matching function for call to ‘VectorXY::VectorXY(int)’
for the vector VectorXY z2(6);
Therefore, I would really appreciate your help. Thanks in advance.

Your error has nothing to do with templates. Consider the following code
struct Int { int i; };
int main()
{
Int z(1); // doesn't compile
}
and you get the error, no matching constructor Int(int).
Classes are an abstraction over something else. It might seem obvious that an int and an Int in this case are the same thing, and constructing one should be like constructing the other. But the compiler doesn't know that, so you need to provide a constructor that passes the argument onto the member.
struct Int
{
int i;
Int(int n) : i(n) {}
};
Note that in C++20, the compiler will actually be able to figure out that you want to use each constructor argument to initialize the corresponding member of your class, so even without a provided constructor, the Int will work like an int.
However, even in that case, your code would not work, since you need to use more complicated rules to construct your members. In your case, you'll need something like
myVector(int n) : vector_a(n), vector_b(n) {}
Assuming that you want the internal vectors to be constructed with the value passed into the constructor. Based on your calling code, it seems that's what you want, but you can write any logic in the constructor.

Related

C++ how to initialize/copy const array member from array parameter in constructor

The following class is meant to store a single bool and an array of 100 integers. I want a constructor that takes as parameters a single bool and a 100-element array (which are then copied into the object). The obvious way to write this is the following
class Info {
private:
const int contents[100];
const bool symmetric;
public:
Info (const int contents[100], bool symmetric) : contents(contents), symmetric(symmetric) {}
// ...
};
But unfortunately this does not compile, the contents argument in the member initialiser list (the third contentson that line) seems to be regarded as a pointer.
Can I get this to work or is this a C++ limitation?
I do not want to use std::array or std::vector for space and efficiency reasons. [edited] Mine is a C++ syntax question and not about whether std::array is efficient or not. The answer may be useful in related situations that do not allow the use of std::array. [end edited]
Initializing in the constructor body does not work, because contents is const.
I am using C++14 with clang (CLion in linux) and come from the Java world.
There is also another way other than std::array, but you should use templates and use variadic parameter feature.
Lets assume that the number of elements is amount then first declare your class like :
#include <utility>
template<size_t amount, typename = std::make_index_sequence<amount> >
class Info;
then define your class as the following:
template<size_t amount, size_t ... _Idx>
class Info<amount, std::integer_sequence<size_t, _Idx...> > {
private:
const int contents[amount];
const bool symmetric;
public:
Info (const int contents_[amount], bool symmetric_) : contents{contents_[_Idx]...}, symmetric(symmetric_) {}
};
now you use your class for any amount without any problem:
const int preinfo[3] = {1,2,3};
Info<3> minfo(preinfo, true);
This method will make it very fast but please note that nothing is free and using this code will make your code to produce a bigger binary after compilation!

template method within template - instance declaration and class method declaration signature differs

I have a templated class and with in that class a further templated method. The templated method requires a different non-explicit but standard typename as shown in the Class and method declaration below.
template <typename T>
class Matrix
{
public:
// constructors
Matrix(int rows, int cols,T _initial);
Matrix():mCols(0),mRows(0),mdata(0)
{ }
Matrix(int rows,int cols,
std::vector<T>&X):mRows(rows),mCols(cols),mdata(X)
{ }
int get_numofrows(); // returns mRows
int get_numofcols() // returns mCols
void show_matrix(); // prints matrix on console, which is really the vector <T> mdata
template<typename E> // <----focus is here
Matrix<E> convert_Matrix(); // <----and here
// other methods not relevant to this problem go here
// ....
private:
int mRows;
int mCols;
std::vector<T> mdata;
};
the implementation details of method convert_Matrix() is shown below:
template<T>
template<E>
Matrix<E> Matrix<T>::convert_Matrix()
{
// creates a vector cast of all elements of underlying
// vector of type T to vector elements of type E
// eg; vector<E> D uses vector copy constructor
std::vector<E> D(this->mdata.begin(), this->mdata.end());
// uses vector D as an argument to create the rest of the matrix
Matrix<E> MX(this->get_numofrows(),this->get_numofcols(),D);
return MX;
}
Intuitively it would seem that the instances in main that use this method (convert_Matrix()) should compile and link but complains of substitution/deduction errors on E only when the convert_Matrix() method is invoked by an instance. It compiles without incident if the method instance is not called in main.
The following code was was developed to test the method convert_Matrix():
#include " Matrix.h"
int main()
{
std::vector<float> Mz = {
139.342, 144.167,149.543,153.678,155.987,155.21,155.23,155.876,
144.112,151.34,153.6789,156.34,159.0124,156.678,156.56,156.6543,
150.456,155.123,160.45,163.876,158.432,156.78,156.123,156.525,
159.567,161.267,162.567,160.67,160.59,159.001,159.675,159.456,
159.876,160.743,161.456,162.432,162.876,155.543,155.123,155.840,
161.111,161.222,161.333,161.678,160.543,157.890,157.1212,157.987,
162.111,162.222,161.333,163.987,162.888,157.543,157.666,157.345,
162.234,162.777,161.888,161.444,163.99,158.775,158.234,158.98
};
Matrix<float> FF(8,8,Mz);
// Matrix<int>BV = FF.convert_Matrix(); <--deduction/substitution error couldn't deduce E
Matrix<int>BV = FF.convert_Matrix<int>();// <---works
BV.show_Matrix();
FF.show_Matrix();
}
I was successful in getting the code above to compile and execute with an instance instantiation of FF.convert_Matrix as shown above but I am not sure if this approach and definition is syntactically accurate. I tried many more type conversions and they all seemed to compile and link and execute correctly without incident (substituting the appropriate type in place of int)
which leads me to the following questions
1) I can understand from a logical perspective, that if the compiler linker complains about type deduction I should try to help it. I tried auto, I tried decltype,
I tried combinations of both, why did the approach I used work? And why didn't the straight forward approach (e.g. class declaration) not work?
2) I stumbled upon this solution illustrated above, by trial and error. Is there some sort of rule in the ISO standard that defines what I did?
3) Is there a better way to do the same thing? Why is the method signature in the class definition, different signature then when it is instantiated in an instance?
4) I do not think this solution issue is best served by a specialization and more code. The solution I stumbled upon works, so why add more code?
I would rather just change the minimum in class declaration and implementation semantics for clarity
Any comments you have or alternate solutions will be greatly appreciated.
The compiler does not look at the type on the left side of an assignment to deduce template parameters. What the compiler sees is FF.convert_Matrix(), and it is unable to deduce the template parameter for convert_Matrix. This is why you need to explicitly specify the template parameter.
The standard library's std::get, when used to extract a value from a tuple based on type, also needs to have the type explicitly specified.

Template function for collection based on member

I have the following structures
struct Obj
{
int a;
int b;
};
class ObjCollection
{
map<int,Obj> collMap;
public:
string getCsvA();
string getCsvB();
};
getCsvA returns a csv of all the a values in the objects of collMap. getCsvB returns the same for all the b values.
Is there a way I can template this function? The reason it becomes complicated for me is that i cannot pass the address of which member i want to generate the csv for, from outside this class ie from my client code. Is there a way to do this?
Note: I can not use C++11.
This looks like you need a function as a parameter to getCsv rather than templates:
Declare the function as string getCsv(int (*selectMember)(Obj)). Furthermore use selectMember([...]) wherever you would have used [...].a in getCsvA.
Now you can call getCsv providing a method returning the right field of Obj, for example:
int selectA(Obj o)
{
return o.a;
}
While a bit inelegant, if you've just a couple fields you can reasonably have getCsvA and getCsvB call a getCsv(A_or_B a_or_b) function, given enum A_or_B { A, B };, then inside getCsv when you you're iterating over collMap say int value = (a_or_b == A) ? iterator->a : iterator->b;, then you put that value into your csv string. Easier than worrying about pointers to member data, functors or templates: when you're comfortable with this level of programming, then you can worry about more abstract approaches (hopefully you'll have C++11 available then, as lambdas are nice for this).
The skeleton of code that you have actually looks okay. It's generally a bad idea to parameterize things that aren't necessary to parameterize. Templates are the most powerful way, but they should really be used with equal discretion.
By adding parameters, you add more opportunities for incorrect code (incorrect function pointer, null pointer, etc...). Using function pointers or virtual methods also creates more difficulty for the compiler in optimizing, since the code executing generally has to be resolved at runtime.
If you were using C++11 instead of C++03 though, using a std::tuple instead of a naked struct would probably make sense, and you would get a templated function as a bonus.
#include <utility>
template<typename... Ts>
class TupleCollection {
public:
template<std::size_t I>
std::string getCsv() {
for (const auto& p : collMap) {
std::string v = static_cast<std::string>(std::get<I>(p.second));
...
}
}
private:
std::map<int, std::tuple<Ts...>> collMap;
};
Then getting the CSV for the relevant field in a compile time safe way would be
tc.getCSV<0>();
tc.getCSV<1>();

Array converted implicitly to container class when passed as argument in C++

I was working on a project and, while playing around with the code, I came across the following peculiar occurrence.
I have two classes. The first holds three floats in an array representing Cartesian coordinates and defines a method to get those points;
class foo
{
protected:
float m_Coordinates[3];
public:
foo(float coordinates[3]);
void GetPoints(int resultArray[]);
};
foo::foo(int coordinates[3])
{
std::copy(coordinates, coordinates+3, m_Coordinates);
}
void foo::GetPoints(float resultArray[])
{
std::copy(m_Coordinates, m_Coordinates+3, resultArray);
}
The second class also stores an array of floats, but its constructor uses foo as a wrapper class to pass the values:
class bar
{
protected:
float m_MoreCoordinates[3];
public:
bar(foo f);
};
bar::bar(foo f)
{
f.GetPoints(m_MoreCoordinates);
//m_MoreCoordinates is passed by reference, so the values in
//m_MoreCoordinates are equal to the values in f.m_Coordinates
//after this line executes
}
Please ignore the fact that the approach I've taken to this code is simply horrible. It started out as an experiment in using arrays. Passing them as arguments, getting them as return types etc.
OK. Here's where I noticed something strange. If I declare an array of floats and pass them as an argument to bar's constructor, the compiler will generate an instance of class foo and pass that to bar for me. See example code below:
int main(int argv, char** argc)
{
float coordinates[] = {1.0f, 2.1f, 3.0f};
//Here the compiler creates an instance of class foo and passes
//coordinates as the argument to the constructor. It then passes
//the resulting class to bar's constructor.
bar* b = new bar(coordinates);
//Effectively, the compiler turns the previous line into
//bar* b = new bar(foo(coordinates));
return 0;
}
When I saw this, I thought it was a pretty neat feature of the code and was wondering how and why it happened. Is it safe to do this? I don't understand how it works, and so I don't want to depend on it. If someone could explain how this works, I'd really appreciate it.
Edit:
Thanks to Mankarse for pointing out how the conversion would be performed in the main. Initially, I had:
//Effectively, the compiler turns the previous line into
//bar* b = new bar(*(new foo(coordinates)));
As you guessed, compiler is implicitly creating a foo object and passing it to bar. Generally, this is considered a bit dangerous as the foo gets constructed without knowledge, to avoid this you can declare foos constructor as explicit. In that case compiler will not implicitly create foo from array of floats and you will get an compiler error.
When you think about it, you use this all of the time. Consider the following:
void foo(std::string argument);
Then, suppose you invoke this function using a string literal:
foo("argument");
this is the same as:
std::string argument("argument");
foo(argument);
It's a pretty useful feature.

Templated operator[]... possible? Useful?

Could you have:
template <class T>
const T &operator[] (unsigned int x)
My thinking was if you have a map<string,string> it would be nice to have a wrapper class which lets you do:
obj["IntVal"]="12";
obj["StringVal"]="Test";
int i = obj["IntVal"];
How close to this can we actually get in C++? Is it worth the pain?
You can also do
class Class {
struct Proxy {
template<typename T> T as() { ... }
template<typename T> operator T() { return as<T>(); }
private:
Proxy(...) { ... }
Proxy(Proxy const&); // noncopyable
Proxy &operator=(Proxy const&);
friend class Class;
};
public:
Proxy operator[](std::string const& s) { ... }
};
Class a;
int i = a["foo"];
int i = a["foo"].as<int>();
T will be deduced to whatever the to be initialized object is. And you are not allowed to copy the proxy. That said, i prefer an explicit as<T> function like another one proposed too.
You can't - in:
int i = obj["IntVal"];
the actual type of T can't be inferred from the context since the return type isn't part of the function signature.
Moreover, storing integer values as strings is not considered as best practices, due to memory and performance considerations ;-)
Not worth it.
Templating the return type means you'd have to explicitly specify the template parameter when you call it. Something like this, maybe I have the syntax wrong:
int i = obj.operator[]<int>("IntVal");
C++ does not deduce template parameters from what you assign the result of the call to, only from the parameters you call the function with.
So you might as well just define a normal function:
int i = obj.get<int>("IntVal");
Or in this case, either do this or implement get using this:
int i = boost:lexical_cast<int>(obj["IntVal"]);
As Amit says, you could define operator[] to return a type which can be converted either to int or to other types. Then your example code can be made to compile without the explicit lexical_cast.
Have you looked at boost variant? Is this what you're looking for?
Well, what you wrote in your sample code doesn't match the question. Right now, you only have the return type templated.
But if you wanted to do something like:
template <class T>
const T &operator[const T& x]
that's valid, though maybe not terribly useful.
A map already provides an overloaded operator[] that does most of what you want. The thing you seem to want that's missing is implicit conversion from a string that happens to contain digits to an integer. One of the fundamental characteristics of C++ is static typing, which says that shouldn't be allowed -- so it's not. It'll be happy to do that conversion if you want, but you'll have to ask for it:
int i = lexical_cast<int>(obj["IntVal"]);
Alternatively, you could create a string-like class that supported implicit conversion to int. Personally, I'd advise against that. I don't object to implicit conversions nearly as strongly as many people do, but that still strikes me as a pretty lousy idea, at least for most general use.