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.
Related
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.
In my job, there are several template mathematical classes (e.g matrix).
An object can be implemented using either floats or doubles (or other numerical types but for this matter, it doesn't really matter).
A double object can only interact with another double object. For this matter the function convert() was implemented for various types, with an implementation similar to this:
Matrix<T2> convert(const Matrix<T1>& m, T2 dummy) {
// create a matrix with type T2 and cast m values into it
// retMatrix(i, j) = (T2)m(i,j)
}
You would call it with:
auto floatMatrix = convert(doubleMatrix, 0.f);
Or the slightly more verbose:
auto floatMatrix = convert(doubleMatrix, float());
I want to add a function like the one below that will enable a cleaner (IMHO) way to call these functions
template <typename T, typename S>
auto convert(S&& s) -> decltype(convert(s, T())) {
return convert(s, T());
}
Now they can be called using:
auto floatMatrix = convert<float>(doubleMatrix);
My question is that my function signature is pretty awkward, I need to repeat the convert(s, T()) both in the decltype and in the actual function body
How do I overcome this?
thanks
edit:
currently, we are not using c++14
edit #2:
the Matrix class was just an example, there are quite a few relevant classes that have the convert() function implemented for them. Each of them already "specialized" like someone suggested in an answer below (deleted meanwhile). I would like to adjust the way convert() is called without re implementing everything
edit #3:
supported types are obviously other than only float and double. please treat the example I gave as an example and not the actual problem I'm trying to solve
the "dummy" functions are already implemented, I was trying to make it work with minimal effort, instead of refactoring 30 functions and all usages
I don't think the question is so far fetched considering cpp14 allows to just remove the -> decltype() thingy...
A little confusing why the need for templates in the first place instead of function overloading:
Matrix<double> convert(const Matrix<float>& m) {
// ...
}
Matrix<float> convert(const Matrix<double>& m) {
// ...
}
float->float and double->double don't seem like meaningful operations that need to be preserved so actually making that a compiler error seems beneficial (whereas the template mechanism might actually succeed and just create an unnecessary copy).
Also the need for the dummy parameter in the first place is confusing without a more complete example.
If you're set on templates (e.g. types go beyond just these two):
template <typename T2, typename T1>
Matrix<T2> convert(const Matrix<T1>& m) {
}
If you're trying to write 1 single generic conversion function across all your other conversion functions you have no way of simplifying what you wrote until C++14 (I mean there are other ways to write it but it seems unlikely to be simpler).
One option might be helper classes that know the conversion type from Matrix for T to Matrix, but they are no prettier than the decltype statement, which is readable and local to the code.
Could Matrix derive from a base class that knows how to generate Matrix from T? Perhaps as a member so you can write:
class MatrixBase
{
public:
template <class T> class To
{ typedef Matrix<T> To; };
};
class Matrix<int>:public MatrixBase {
// ...
};
All this just to write: -> S::To<T>::To
As you say, come the C++14 revolution you can do the fully automatic return type thing.
Let's say I have several functions defined like this:
template <typename T>
inline void read<bool>(T **data) {
//some code
}
template <typename T>
inline void read<double>(T **data) {
//some other code
}
template <typename T>
inline void read<int>(T **data) {
//also different code
}
Now, I create another function defined like this:
template<typename T>
inline void readMultiple(T **data, int counter) {
for (int i = 0; i < counter, ++i) {
read<T>(data);
}
}
(1)That would call the appropriate read<T>(T **data) implementation based on the type T, right?
(2)If I were to specify a type that is not one of the three above, I'd get a compilation error, since that function is not defined, right?
(3)Also, can I make this call:
double **d;
read<double>(d);
to ensure that I called the implementation for double?
I know I'd get the same result without the <double> part, but this way I'm ensuring that double is passed to the function, where as doing it without <double> would allow for d to be a int or a bool and the code would still compile, silently introducing an error.
(1)That would call the appropriate read<T>(T **data) implementation based on the type T, right?
Yes, assuming the specializations are visible at the point where read<T>(data) is encountered.
(2)If I were to specify a type that is not one of the three above, I'd get a compilation error, since that function is not defined, right?
You haven't provided your declaration of the template read() function, so this can't be answered. Assuming that you have declared it like template <typename T> void read(T**); and have not defined it anywhere then yes, you would get a link-time error when the linker is unable to find an implementation of the requested specialization.
(3)Also, can I make this call:
double **d;
read<double>(d);
to ensure that I called the implementation for double?
You can, though <double> is superfluous and will be inferred.
... silently introducing an error.
If the thing you're passing is a bool** then it would not be an error to use the bool specialization. I don't really see any benefit from explicitly providing the template arguments. If bool** is the wrong type then presumably you would be getting errors somewhere else, anyway.
I guess it depends on what you mean by "silently introducing an error." It's not clear what kind of error you're trying to prevent. I can come up with a contrived example, but contrived examples rarely represent real-world dangers.
Two side notes:
The syntax for your specializations is incorrect. It should be template <> inline void read<bool>(bool **data) { /* ... */ } for example.
There's no need for templates here at all, you can just have three function overloads. Having an undefined template function with explicit specializations is an anti-pattern; overloads are the recommended way to implement the same thing.
I'm trying to find is there's a way to check if a class is a functional because i want to write a template which uses it?
Is there an easy way to do this? Or do I just wrap things in a try/catch? Or perhaps the compiler won't even let me do it?
If you have a function template written like:
template <typename T>
void f(T x)
{
x();
}
you will be unable to instantiate it with any type that is not callable as a function taking no arguments (e.g., a class type that overloads operator() taking no arguments is callable as a function that takes no arguments). You would get a compilation error if you tried to do so.
This is the simplest way to require the type with which a template is instantiated to have certain properties: just rely on the type having those properties when you write the template, and if the type doesn't have one of the required properties, it will be impossible to instantiate the template with that type.
There are quite a few ways a parameter type can be applicable to the call syntax
Type is a pointer or reference to a function type, or
Type is a class-type which has a conversion function to one of the types in 1., or has an applicable operator().
The current C++ cannot check for 2., so you are left without checking, like the other answers explain.
This would fall under doing it and getting a compiling error. When the code is compiled the template function or template classes are are expanded for the types used as if there were duplicate copies of that template code, one for each type.
So you can basically do whatever and as long as all the types used for your templates support it you have no problem. If they don't support it you have a compiling error and you can't run your code without fixing it.
template <typename T>
void DoIt(T a)
{
a.helloworld();//This will compile fine
return a();//This will cause a compiling error if T is B
}
class A
{
public:
void a.helloworld(){}
void operator()(){}
};
class B
{
public:
void a.helloworld(){}
};
int main(int argc, char**argv)
{
A a;
B b;
DoIt(a);
DoIt(b);//Compiling error
return 0;
}
If you actually need a test to see if type T implements an operator() of some given signature then you could use the same SFINAE trick used to identify the existence of any other class member that is discussed here: C++ "if then else" template substitution
I'm trying to do a base template class which parameter T must be a structure.
When I use a variable declared as being of type T (both in the template class as in a class that extends it defining T) GCC fails to compile it:
GCC error: invalid use of incomplete
type ‘struct x'
Despite it working on VC I understand that it doesn't work because it shouldn't because the compiler isn't aware per the standard of the types that T represent.
Is there a way of making explicit that the type must be a structure?
What I'm doing in the code that works in VC is:
In the base class:
T* x
new T
sizeof(T)
In those that extend it:
x->member
Edit: I tried to take the relevant code. Here it is:
struct SomeStructureType
{
int memberA;
int memberB;
}
template <typename T> class Base
{
protected:
T* s;
void addMember(string name,void* offset);
Base()
{
s = new T;
}
};
class Extender : public Base<SomeStructureType>
{
public:
Extender()
{
addMember("memberA",&s->memberA);
}
}
Most (if not all) times the compiler complains about using an 'incomplete' type the problem resides in trying to use a forward declared class that has not been completely defined.
There are just so many things you can do with an incomplete type: define functions that take or return the type or references to it, define reference or pointer variables of that type... and others you cannot do: define variables of that type, create an object of the type, call any method or request any attribute from the type...
The question in the title can be dismissed; C++ classes and structures cannot be distinguished other than by source code inspection.
The explanation is quite confusing. There's apparently a message about struct x yet the example code contains not a single x. That tells me that you're not careful about matching up errors and source code. Once you do that, you often don't need StackOverflow anymore - you'll see the problem yourself.
There is nothing wrong with the code you've posted other than two missing semicolons after class/struct definitions: http://codepad.org/yfbHa8sO
The problem isn't related to the fact that T must be a structure. The problem is in that one of the structures (that I'm using in my code but was not created by me) is said to be incomplete by gcc. Anyway, I removed the class that uses this structure and other classes compile with the same base class. So, is up to me to fix it and what I assumed about the problem was wrong.