The following code works when used without C++ classes (Arduino code);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midiA);
This creates a variable midiA with the correct type. The macro definition is:
#define MIDI_CREATE_INSTANCE(Type, SerialPort, Name) \
midi::MidiInterface<Type> Name((Type&)SerialPort);
However, I want to use this inside a class (to create a class variable midiA), but I cannot get it to work.
What I have now is:
class MidiHandler
{
midi::MidiInterface<(HardwareSerial&) Serial1)> midiA;
}
However, I get the following error:
MidiHandler.h: 23:39: error: type\value mismatch at argument 1 in template parameter list for 'template<class SerialPort, class _Settings> class midi::MidiInterface
midi*: MidiInterface<((HardwareSerial&)Serial1)> midiA
I think I might need to add the template to the class MidiHandler, also I wonder if I need to initialize it in the constructor.
Disclaimer: I don't have an Arduino to compile and test this, but from the pure C++ point of view, I would declare the member in the class declaration and initialize it in the constructor. Like this:
class MidiHandler
{
public:
MidiHandler(HardwareSerial& serial_port)
: midiA(serial_port)
{ }
private:
midi::MidiInterface<HardwareSerial> midiA;
};
Then, instantiate the class like this:
MidiHandler handler((HardwareSerial&) Serial1);
DETAIL:
The MidiHandler class has a member variable named midiA of type midi::MidiInterface<HardwareSerial>, which is a template with one template parameter (the Type parameter from the macro). HardwareSerial is used as the value for the template parameter.
The type midi::MidiInterface<HardwareSerial> has a constructor requiring one parameter of type HardwareSerial&. Therefore, MidiHandler::MidiHandler, the MidiHandler class constructor, needs a parameter of the same type to be used to construct midiA.
Finally, Serial1 is passed as the constructor parameter to handler. Serial1 must be of type HardwareSerial& or convertible to it. The C stile cast, (HardwareSerial&), may or may not be needed depending on the type of Serial1, but I put it there since the macro had it.
As is shown in the define:
#define MIDI_CREATE_INSTANCE(Type, SerialPort, Name)
midi::MidiInterface<Type> Name((Type&)SerialPort);
So substituting in Your values should be:
midi::MidiInterface<HardwareSerial> midiA((HardwareSerial&)Serial1);
Answer as result of the accepted answer by Luis Guzman:
In header file:
midi::MidiInterface<HardwareSerial> midiA;
midi::MidiInterface<HardwareSerial> midiB;
midi::MidiInterface<HardwareSerial> midiC;
In constructor:
MidiHandler::MidiHandler()
: midiA(Serial1),
midiB(Serial2),
midiC(Serial3)
Related
I'm working on a project using interface based programming. The first part of this is for context just in case someone says I'm doing something completely wrong or has a different approach that fixes my issue.
I have a container class that includes several abstract interface classes. These define functions that return data I need.
This container class has a vector of parts that do not know about the container class, and therefore does not include the interface headers.
Every part is an object of the same type. When creating these objects, it passes a function pointer as an argument to the constructor of the child objects. This argument is a pointer to a function defined in one of the interface classes.
I'm trying to pass a pointer using &iTheInterfaceClass::theDataFunction to a constructor expecting U16(*pDataFunction)().
This results in the error
cannot convert 'U16 (iTheInterfaceClass::*)() {aka short unsigned int (iTheInterfaceClass::*)()}' to 'U16 (*)() {aka short unsigned int (*)()}' in initialization
If the parts include the .h file, I can get this to work, as I just match the prototype to include the namespace in the constructor. However, this breaks my abstraction. If each part includes a different interface, I have to create individual classes for each, even though the functionality is identical.
Is there anyway to get the prototypes to match without completely readjusting my strategy here?
As you've said yourself, your constructor expects the following type (excluding names):
U16 (*)()
However, you are trying to pass the following type:
U16 ( iTheInterfaceClass::* )()
Your constructor accepts free functions and class functions that are static, but you are trying to pass a non-static member function.They are not of the same type.
You could provide an overload for your constructor that takes in a member function as well as a reference or pointer to the object that the member function will be called on.
It could look something like:
public:
typedef U16( iTheInterfaceClass::*MemberFunctionPtr )();
MyContainer( iTheInterfaceClass& member, MemberFunctionPtr function ) : ... { ... }
Assuming you stored that information in some variables somewhere in the class, you could then call that function like so:
( member.*function )();
Where member is the variable that holds a reference to the object that you want to call the function on and function is the variable which holds the pointer to said member function.
If create an enum inside a struct for readability, mentioned here
How to avoid name conflicts for two enum values with the same name in C++?
I am planning to add more enums, here and in other situations, I just wanted to know why the struct wasn't compiling. Coming from C# and Java I was hoping for a simpler syntax –
And have the struct as the parameter to a constructor in a class, I cannot call it from the main.cpp of a console application.
It gives me the error **no matching function for call toBarEnc::BarEnc(BarEnc::Scheme::eScheme)’ ** main.cpp
Here is the Class
class BarEnc {
public:
struct Scheme
{
enum eScheme
{ ADJ1M2, ADJ3M6
};
};
BarEnc();
BarEnc(BarEnc::Scheme scheme);
}
in main.cpp
I call it
BarEnc barEnc = BarEnc(BarEnc::Scheme::ADJ3M6);
But if I change the parameter to an int in the constructor the code compiles
BarEnc(int scheme);
If I change it to the enum the code compiles
BarEnc(BarEnc::Scheme::eScheme scheme);
But when it is a struct, it does not compile. I am relative new to C++, using GCC 4.6 to compile on Linux, using 99 standard.
Is there a reason why I can't use a struct as a parameter?
Simple question: how your enum value should be converted to struct?
Simple answer: there is no way, since there is no suitable constructor.
Your struct has no members, it has only type (enum), so, I have no idea, what you want to do.
When you declare the constructor as
BarEnc(BarEnc::Scheme scheme);
you tell the compiler that the BarEnc constructor takes a structure as argument, and so you can't pass the enumeration value as it's an enumeration and not the structure.
In this case there is really no use for a separate structure just to define the enumeration, you can declare it directly in the surrounding class:
class BarEnc {
public:
enum eScheme {
ADJ1M2,
ADJ3M6
};
BarEnc(eShceme scheme);
};
Then when creating BarEnc objects you pass the enumeration value:
BarEnc barenc(BarEnc::eScheme::ADJ1M2);
You can use a struct as parameter.
But your struct BarEnc::Scheme in fact has no member.
and the const value BarEnc::Scheme::ADJ3M6 's type is BarEnc::Scheme::eScheme, it cannot auto convert to a struct.
I have a c++ class such as the following:
class some_class {
protected:
decide_later some_variable;
public:
void some_random_function();
};
void some_class::some_random_function() {
decide_later another_variable;
}
The problem is that I don't know what variable type some_variable will be until I create an instance of the class. What I want to do is something like the following:
some_class class_instance(std::string);
And that would set decide_later to use std::string (or int, or double, or whatever it is told to use). In addition, it would be great if I could use decide_later as a variable type later on in other functions that are members of the class. For example, in the function some_random_function().
I have tried using boost::any to do this, but it seems to only work for numeric types. Besides, I think it would be more efficient if I could actually set the actual variable type.
Is this possible?
You are looking for templates. Declare your class like:
template <typename T> class some_class {
protected:
T some_variable;
public:
void some_random_function() {
T another_variable;
}
};
and instantiate it with:
some_class<std::string> class_instance();
If you know the type statically when you create the instance, you should use C++ templates and make the type a template parameter.
If you know it only dynamically (i.e. based on user input), you can either branch then and instantiate the template with different type parameters, or you can go for a completely dynamical solution (like boost::any or equivalent).
However, I believe that if you can't do this with templates then there's something wrong in your program design. The idea of C++ static typing is that types are known at compile time. Normally in object-oriented design you would use polymorphism instead of weak typing.
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.
Suppose I have code like this:
template<class T, T initial_t> class Bar {
// something
}
And then try to use it like this:
Bar<Foo*, NULL> foo_and_bar_whatever_it_means_;
GCC bails out with error (on the above line):
could not convert template argument
'0' to 'Foo*'
I found this thread: http://gcc.gnu.org/ml/gcc-help/2007-11/msg00066.html, but I have to use NULL in this case (ok, I could probably refactor - but it would not be trivial; any suggestions?). I tried to overcome the problem by creating a variable with value of NULL, but GCC still complains that I pass variable and not address of variable as a template argument. And reference to a variable initialized with default ctor would not be the same as NULL.
Rethinking your code is probably the best way to get around it. The thread you linked to includes a clear quote from the standard indicating that this isn't allowed.
To accept Bar<Foo, NULL>, you need
template <typename T, int dummy> class Bar; /* Declared but not defined */
template <typename T> class Bar <T,NULL> { /* Specialization */ };
since typeof(NULL)==int.
It seems to be the same problem as passing a string literal as non-type template parameter: it's not allowed. A pointer to an object is allowed as template parameter if the object has external linkage: this to guarantee the uniqueness of the type.
Have you tried:
Bar<Foo*, (Foo*)NULL> foo_and_bar_whatever_it_means_;
?
or reinterpret_cast(0)?
#Dan Olson: there seems to be quite easy workaround.
Create a parent class with only one template parameter. Add a virtual function returning T. For base class it should be hardcoded to be NULL. For deriving class it would return the second template parameter.