I am a .Net C# programmer trying to program in C++. I have an application that uses a third party library. When i try and use an Enum from the library in a function for this library I get an error message of type not allowed:
I have included the library:
#include <Trading.h>
using namespace Trading;
Trading.h includes Enumerations.h that contains:
/// Returns string representation.
FOO std::string enumToString (TimeInForce::Enum);
/// Trading session event type.
struct FOO TradSesEvent
{
/// #copydoc TradSesEvent
enum Enum
{
...
};
};
Code of the Application.cpp simplified to the problem:
#include <Trading.h>
using namespace Trading;
class Application
{
public:
Application(const Settings& settings) : settings_(settings)
{
orderBook_.reset(new OrderBook());
...
}
private:
// Store of orders sent to counterparty.
PtrTraits<OrderBook>::UniquePtr orderBook_;
void onSendNewOrder(Order& newOrder)
{
//create unique_ptr to fill in the order values and sen
PtrTraits<Order>::UniquePtr order(new Order(orderBook_->newId()));
order->timeInForce = TimeInForce.Day;
...
}
};
Error message:
struct Application::TimeInForce type name is not allowedC/C++(254)
The syntax for naming a member of an unscoped enum declared in a class or namespace TimeInForce is:
TimeInForce::Day
The period (.) is used for accessing non-static members of classes.
Related
(Not sure whether this is exclusively a C/C++ issue)
I’m currently fragmenting elements of a large Arduino project into reusable libraries - so far soo good.
However, a number of methods in the libraries return special structs which are declared in a data-types.h file contained in each library. The problem I have now is I'm unable to import/utilise these structs in my main sketch. I've tried declaring a variable of the DataTypes class in the main library header file and accessing the structs through it, but I get error error: invalid use of 'struct DataTypes::_theStructNameHere_t'
How would I go about accessing these structs from the library in my main sketch to declare as a variable type? I don't want to have to copy the header file which contains the structs from the library into my sketch, and I also don't want to have to create a separate library just for this single header file of structs!
Here's a quick example of what I mean:
Main.cpp:
#include <Arduino.h>
#include <MyLibrary.h>
MyLibrary myLib;
void setup() {
(This is declared in the library) myLib.dataTypes._theStructNameHere_t response = myLib.getASpecialValueWhichIsOfType_theStructNameHere_t()// Gives "error: invalid use of 'struct DataTypes::_theStructNameHere_t'""
// Example usage of the struct:
Serial.print("\n Loop Card Status: ");Serial.print(response.loop_status, HEX);
if (response.number_allocated > 0) {
Serial.print("\n Devices Allocated: ");Serial.print(response.number_allocated, HEX);
} else {
if (response.loop_status != 0x123) {
// Some condition
} else {
// Something else
}
}
}
void loop() {
...
}
Library Structure:
src/
- /data-types/
- - data-types.h
- MyLibrary.cpp
- MyLibrary.h
Library Header MyLibrary.h:
#ifndef _MYLIBRARY_H_
#define _MYLIBRARY_H_
#include <Arduino.h>
#include "./helpers/helpers.h"
...
#include "./data-types/data-types.h"
class MyLibrary {
public:
Uart *_commPort;
Helpers helpers;
...
DataTypes dataTypes;
DataTypes::_theStructNameHere_t getASpecialValueWhichIsOfType_theStructNameHere_t();
...
protected:
private:
};
#endif // _MYLIBRARY_H_
DataTypes Class data-types.h:
#ifndef _RESPONSE_TYPES_H
#define _RESPONSE_TYPES_H
class DataTypes
{
public:
struct _theStructNameHere_t
{
bool successful;
uint8_t loop_status;
uint8_t number_allocated;
uint8_t highest_address;
uint8_t number_inputs;
uint8_t number_outputs;
}
..even more..
private:
}
#endif // _RESPONSE_TYPES_H
I was able to obtain a MCVE from your example:
class DataTypes
{
public:
struct _theStructNameHere_t
{
};
};
class Library
{
public:
DataTypes dataTypes;
DataTypes::_theStructNameHere_t getMyDataType();
};
int main(int argc, char *argv[])
{
Library myLib;
myLib.dataTypes._theStructNameHere_t response;
}
which gives a similar error as your code:
~$ g++ test.cpp
test.cpp: In function 'int main(int, char**)':
test.cpp:20:21: error: invalid use of 'struct DataTypes::_theStructNameHere_t'
myLib.dataTypes._theStructNameHere_t response;
The problem is that you use an instance to access the struct type/name. To fix it, replace
myLib.dataTypes._theStructNameHere_t response = ...;
with
DataTypes::_theStructNameHere_t response = ...;
Notes:
Instead of using classes to create separate namespaces, please consider using namespaces directly. This is a feature of C++ which is available under Arduino.
namespace Library {
namespace DataTypes {
struct _theStructNameHere_t
{
...
};
...
} /*** namespace Library::DataTypes ***/
} /*** namespace Library ***/
Please read StackOverflow guidelines concerning how to ask a good question, in particular the section about Mininimal, Complete and Verifiable Example.
Sooner or later someone will tell you that there is no such thing as C/C++; C is C and C++ is C++; Arduino lives in its own world, even if is based on C++. Thus, you might want to remove C and C++ tags from your question.
To my current C++ project, I use an external library (1 big header) from a third party. This header provides multiple C like functions to drive hardware. To make it easier to use in C++, I wrote a C++ class to wrap those functions and hide this header with a pimpl implementation.
Some parameters for those functions are defined by preprocessor directives #define in their main header. I would like to use the value of those parameters outside my wrapper class but without include this header.
I tried to use forward declared enum in my C++ class. But members of my enum are not available outside the source file where they are defined
external_lib.h
#define PARAM_A_VAL_0 0
#define PARAM_A_VAL_1 1
bool external_function_param_a(int param_a);
wrapper.h
class wrapper
{
enum PARAM_A : int;
...
bool SetParamA(wrapper::PARAM_A a);
}
wrapper.cpp
#include <wrapper.h>
#include <external_lib.h>
enum wrapper::PARAM_A: int
{
VAL_0 = PARAM_A_VAL_0,
VAL_1 = PARAM_A_VAL_1
};
bool wrapper SetParamA(wrapper::PARAM_A a)
{
return external_function_param_a(a);
}
main.cpp
#include <wrapper.h>
int main()
{
wrapper w;
w.SetParamA(wrapper::PARAM_A::VAL_0);
// compilation error : VAL_0 not a member of wrapper::PARAM_A
}
Is there something wrong in my solution or this idea is just impossible? Is there a better solution. Create a lot of members to the class wrapper doesn't seem to be a good idea neither a switch on enum in all function members.
If you must keep compile-time const-ness, you would not be able to avoid inclusion of external header, as explained in this Q&A.
If compile-time const-ness is not a requirement, you could separate declarations and definitions of wrapper::PARAM_A::VAL_NNN constants, like this:
Header:
struct wrapper {
class PARAM_A {
int val;
PARAM_A(int val) : val(val) {}
friend class ::wrapper;
public:
static const PARAM_A VAL_0;
static const PARAM_A VAL_1;
};
bool SetParamA(wrapper::PARAM_A a);
};
Implementation:
const wrapper::PARAM_A wrapper::PARAM_A::VAL_0 = wrapper::PARAM_A(PARAM_A_VAL_0);
const wrapper::PARAM_A wrapper::PARAM_A::VAL_1 = wrapper::PARAM_A(PARAM_A_VAL_1);
bool wrapper::SetParamA(wrapper::PARAM_A a)
{
return external_function_param_a(a.val);
}
Now the use of the API remains the same as in your example:
wrapper w;
w.SetParamA(wrapper::PARAM_A::VAL_0);
w.SetParamA(wrapper::PARAM_A::VAL_1);
Demo.
Note the way the class PARAM_A hides the int value: since it is no longer an enum, direct use in place of int is no longer possible, so the call to external_function_param_a needs to "unwrap" the value.
For example I have the following class:
namespace someName
{
class someClass
{
Q_ENUMS(ESomeEnum)
public:
enum ESomeEnum {ENUM_A, ENUM_B, ENUM_C};
// ... some other things ..
}
}
Q_DECLARE_METATYPE(someName::someClass)
Is there a way to use QMetaEnum::valueToKey or QMetaEnum::keyToValue ?
Tried the method in this answer but got the following error:
error: static assertion failed: QMetaEnum::fromType only works with enums declared as Q_ENUM or Q_FLAG
#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
I can employ X-Macros to get my desired output but it would also be nice to learn more tricks in Qt.
No, there isn't, because Q_ENUM's functionality is implemented in code generated by moc, and moc ignores classes that are neither Q_OBJECT nor Q_GADGET. There's no reason for not using a Q_GADGET since it has no effect on object size: adds no virtual methods nor data fields.
The following demonstrates this:
#include <QtCore>
namespace Ns {
class Class {
Q_GADGET
public:
enum ESomeEnum {ENUM_A, ENUM_B, ENUM_C};
Q_ENUM(ESomeEnum)
};
}
int main() {
auto metaEnum = QMetaEnum::fromType<Ns::Class::ESomeEnum>();
qDebug() << sizeof(Ns::Class) << metaEnum.valueToKey(Ns::Class::ENUM_A);
}
#include "main.moc"
Output:
1 ENUM_A
On this particular platform (and many others), empty classes are of size 1.
Yes, since 5.8 you can do:
namespace MyLibrary
{
Q_NAMESPACE
enum class MYLIBRARYSHARED_EXPORT MyEnumClass
{
...
};
Q_ENUM_NS(MyEnumClass)
...
} // namespace MyLibrary
Q_ENUM is like the old Q_ENUMS but with these differences:
It needs to be placed after the enum in the source code.
Only one enum can be put in the macro.
It enables QMetaEnum::fromType<T>().
These enums are automatically declared as a QMetaTypes (no need to
add them in Q_DECLARE_METATYPE anymore).
enums passed to qDebug will print the name of the value rather than
the number.
When put in a QVariant, toString() gives the value name. The value name
is printed by QCOMPARE (since Qt 5.6)
Taken from WOBOQ blog post on the topic, read it for additional information regarding Q_ENUM vs Q_ENUMS.
I've written part of a class in C++ and I want to be able to use it in conjunction with a Python GUI, so I'm using Boost.Python to try and make it easy. The issue I'm running into is that in following their guide (http://www.boost.org/doc/libs/1_55_0/libs/python/doc/tutorial/doc/html/python/exposing.html), I keep getting the following exception whenever I run bjam:
PacketWarrior/pcap_ext.cc:21:5: error: too few template arguments for class template 'class_'
Obviously it's complaining at me for omitting what they claim are optional arguments to the 'class_' template function, but I can't figure out why. I'm assuming it's a compiler issue but I don't know how to fix it. I'm running OS X 10.9 and using darwin for the default toolset, but GCC throws the same error. My Boost version is 1_55_0 if that helps at all.
Class header file (header guards omitted):
#include <queue>
#include "pcap.h"
#include "Packet.h"
class PacketEngine {
public:
PacketEngine();
~PacketEngine();
const char** getAvailableDevices(char *error_buf);
bool selectDevice(const char* dev);
Packet getNextPacket();
private:
char *selected_device;
char **devices;
int num_devices;
std::queue<Packet> packet_queue;
};
The cc file containing the references to Boost.Python and my class:
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include "PacketEngine.h"
BOOST_PYTHON_MODULE(pcap_ext) {
using namespace boost::python;
class_<PacketEngine>("PacketEngine")
.def("getAvailableDevices", &PacketEngine::getAvailableDevices);
}
And my bjam file (irrelevant parts and comments omitted):
use-project boost : ../../../Downloads/boost_1_55_0 ;
project
: requirements <library>/boost/python//boost_python
<implicit-dependency>/boost//headers
: usage-requirements <implicit-dependency>/boost//headers
;
python-extension pcap_ext : PacketWarrior/pcap_ext.cc ;
install convenient_copy
: pcap_ext
: <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION
<location>.
;
local rule run-test ( test-name : sources + )
{
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
}
run-test pcap : pcap_ext pcap.py ;
Any ideas as to how to circumvent this exception are greatly appreciated! I looked into the obvious route of just adding the optional parameters but I don't think they're relevant to my project. The class_ definition can be found here:
http://www.boost.org/doc/libs/1_37_0/libs/python/doc/v2/class.html
In short, include either:
boost/python.hpp: The Boost.Python convenient header file.
boost/python/class.hpp: The header that defines boost::python::class_.
The current included header files are declaring class_ with no default template arguments from def_visitor.hpp.
Also, trying to directly expose PacketEngine::getAvailableDevices() will likely present a problem:
It accepts a char* argument, but strings are immutable in Python.
There are no types that automatically convert to/from a const char** in Boost.Python.
It may be reasonable for a Python user to expect PacketEngine.getAvailableDevices() to return an iterable type containing Python strs, or throw an exception on error. This can be accomplished in a non-intrusive manner by writing a helper or auxiliary function that delegates to original function, but is exposed to Python as PacketEngine.getAvailableDevices().
Here is a complete example based on the original code:
#include <exception> // std::runtime_error
#include <boost/python.hpp>
namespace {
const char* devices_str[] = {
"device A",
"device B",
"device C",
NULL
};
} // namespace
class PacketEngine
{
public:
PacketEngine() : devices(devices_str) {}
const char** getAvailableDevices(char *error_buf)
{
// Mockup example to force an error on second call.
static bool do_error = false;
if (do_error)
{
strcpy(error_buf, "engine not responding");
}
do_error = true;
return devices;
}
private:
const char **devices;
};
/// #brief Auxiliary function for PacketEngine::getAvailableDevices that
/// provides a more Pythonic API. The original function accepts a
/// char* and returns a const char**. Both of these types are
/// difficult to use within Boost.Python, as strings are immutable
/// in Python, and Boost.Python is focused to providing
/// interoperability to C++, so the const char** type has no direct
/// support.
boost::python::list PacketEngine_getAvailableDevices(PacketEngine& self)
{
// Get device list and error from PacketEngine.
char error_buffer[256] = { 0 };
const char** devices = self.getAvailableDevices(error_buffer);
// On error, throw an exception. Boost.Python will catch it and
// convert it to a Python's exceptions.RuntimeError.
if (error_buffer[0])
{
throw std::runtime_error(error_buffer);
}
// Convert the c-string array to a list of Python strings.
namespace python = boost::python;
python::list device_list;
for (unsigned int i = 0; devices[i]; ++i)
{
const char* device = devices[i];
device_list.append(python::str(device, strlen(device)));
}
return device_list;
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<PacketEngine>("PacketEngine")
.def("getAvailableDevices", &PacketEngine_getAvailableDevices);
}
Interactive usage:
>>> import example
>>> engine = example.PacketEngine()
>>> for device in engine.getAvailableDevices():
... print device
...
device A
device B
device C
>>> devices = engine.getAvailableDevices()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: engine not responding
So I have this c++ code which I have written for c++0X. It used to compile in MSVC 2012, but now I switched to MingW64 4.8.1 because I was dissatisfied with the lack of C++11 support in MSVC. The following is part of some code which implements a simple Entity/Component System.
This is the error I get:
if(e->components.find(T::ID) == e->components.end())
undefined reference to
`EL::Position3DComponent::ID' ELEntityManager.h /Elementium/Elementium line
64 C/C++ Problem
which is related to using T::ID...
Here is some further explanation of what I used to use this code for in MSVC 2012:
In every component, I have a static const ELComponentID member which is initialized to the component's id. This is used because I need to easily get the entities which have a certain component, so I'm using a multimap in the ELEntityManager whose key is ELComponentID and whose value is a unique_ptr containing the ELEntity who has such a component.
In the ELEntity class, I use an unordered_map whose key is ELComponentID and whose value is a unique_ptr containing the ELComponent in question.
Yes it does take up a little more memory, but I do this mainly for access speed.
file ELEntityManager.h:
//Includes
#include <map>
#include <memory>
#include "ELEntity.h"
#include "ELComponent.h"
namespace EL{
class ELEntityManager
{
public:
//...
template<typename T> void addComponent(std::unique_ptr<ELEntity> e, std::unique_ptr<ELComponent> c)
{
if(c == nullptr || e == nullptr)
return;
if(e->components.find(T::ID) == e->components.end()) //***** <-- This is where I get the error.
{
//...
}
//...
}
//...
private:
//******************************************
// Private data members
//******************************************
std::multimap<ELComponentID, std::unique_ptr<ELEntity> > entities;
};
};// End namespace
file ELEntity.h:
//Includes
#include <unordered_map>
#include <memory>
#include "ELComponent.h"
namespace EL{
class ELEntity
{
friend class ELEntityManager;
//...
private:
//******************************************
// Private data members
//******************************************
/**The map of ComponentIDs with their components.*/
std::unordered_map<ELComponentID, std::unique_ptr<ELComponent> > components;
};
};// End namespace
file ELComponent.h:
//Includes
#include <unordered_map>
#include <functional>
#include <string>
#include <vector>
#include "ELMath.h"
namespace EL{
/**
* Component IDs.
*/
enum ELComponentID {
LogicalDevice = 1, // Start the enum at 1.
Viewport,
Position3D,
Position2D,
Orientation,
PhysicsRK4
};
/**
* Base component class.
*/
struct ELComponent
{
};
/**
* Position3D component, derives from ELVector3D in EL::Math.
*/
struct Position3DComponent: public ELComponent, EL::Math::ELVector3D
{
static const ELComponentID ID = Position3D;
};
//...
then I have this in main.cpp as a test (with all the required includes, etc...):
EL::ELEntityManager em;
std::unique_ptr<EL::ELEntity> e(new EL::ELEntity());
std::unique_ptr<EL::Position3DComponent> obj(new EL::Position3DComponent());
obj->x = 1.0;
obj->y = 2.0;
obj->z = 3.0;
em.addComponent<EL::Position3DComponent>(std::move(e), std::move(obj));
Now my question is, am I doing something wrong which is gcc specific, is the T::ID not supported in gcc/mingw, or has anything changed in the final c++11 implementation which wasn't in for MSVC 2012?
How do I fix this error? If it can't be done anymore in c++11, or if there's a bug in gcc, can I do this any other way?
Thanks a lot in advance for your replies! :)
I think GCC is right. From the code you posted, it seems to me you are not providing a definition for your static data member.
Since you are passing T::ID in input to std::unordered_map::find(), which takes its argument by reference, you are odr-using ID (ODR stands for One Definition Rule, and odr-using means, in short, that the compiler needs to know the address of that object).
Since the address of the static data member is needed, but no definition at global namespace is provided, you end up with an unresolved symbol error from the linker.
Per paragraph 9.4.2/3 of the C++11 Standard:
If a non-volatile const static data member is of integral or enumeration type, its declaration in the class
definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression
is a constant expression (5.19). [...] The member shall still be defined
in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not
contain an initializer.
Therefore, to solve the problem, just add a definition at namespace scope in a .cpp file (or in a header included by just one .cpp file):
const ELComponentID Position3DComponent::ID;