I'm messing around with (a bit old) SimIt-ARM 3.0. The SimIt-ARM 3.0 has issgen (ISS generator) based on (ARMv5) ISA defined using internal language defined using Lex specification & Yacc grammar. In particular it has a symbol_table class based on STL hash_map (which is not part of the C++ Standard Library, and which is now deprecated).
The problem: the hash_map behaves unexpectedly. Here is a demo using the original test. We see that output differs between -O0 and -O1.
Can someone help me to figure out what it the root cause?
UPD: here is the MRE:
#ifdef __GNUC__
#if __GNUC__ < 3
#include <hash_map.h>
namespace Sgi { using ::hash_map; using ::hash; }; // inherit globals
#else
#include <ext/hash_map>
#if __GNUC_MINOR__ == 0 && __GNU_C__ == 3
namespace Sgi = std; // GCC 3.0
#else
namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later
#endif
#endif
#endif
#include <string>
#include <iostream>
#include <vector>
#include <cstring>
struct strEql
{
bool operator()(const char* sz1, const char* sz2)
{
return strcmp(sz1,sz2) == 0;
}
};
typedef Sgi::hash_map<const char *, unsigned int,
Sgi::hash<char *>, strEql> hash_map;
hash_map hasher;
unsigned int idx = 1;
void insert(const std::string& key)
{
hash_map::iterator it = hasher.find(key.c_str());
if (it==hasher.end())
{
hasher[key.c_str()] = idx++;
}
}
void print_hasher(void)
{
for(hash_map::iterator it = hasher.begin(); it != hasher.end(); it++)
{
std::cout << "fisrt: " << it->first << ", second: " << it->second << std::endl;
}
}
int main(void)
{
insert("xxx");
insert("yyy");
print_hasher();
}
Invocations and output:
$ g++ mre.cpp -Wno-deprecated -O0
fisrt: xxx, second: 1
fisrt: yyy, second: 2
$ g++ mre.cpp -Wno-deprecated -O1
fisrt: xxx, second: 1
In insert you are creating a temporary std::string key, the pointer returned from key.c_str() is therefore only valid until the end of the function.
Even if it was still valid then multiple calls to insert with the same string wouldn't necessarily produce the same address, equally calls with different strings might produce the same address so your hash table will be completely broken.
If you really want to hash based on the addresses you need to make sure you are only using string literals which will always have the same address (though I don't think there is any guarantee that two literals with the same value will have the same address) and will be valid for the duration of your program:
void insert(const char* key)
{
hash_map::iterator it = hasher.find(key);
if (it==hasher.end())
{
hasher[key] = idx++;
}
}
https://godbolt.org/z/6r18T16P9
You still need to be careful as its easily possible to pass a non-literal to insert and you'll be back to your original problem:
insert(std::string("yyy").c_str());
https://godbolt.org/z/EaGMvhPrE
Related
I want to mangle a name passed to a macro to use it as a name of a function. For example I have a macro called foo as below:
#define foo(name) void name(const string& in) { \\do something }
But I want this macro to be called with parameter like this foo(Bar::do) so I have to change the name to the proper one to use it as a function.
Is there any way to able to implement this? I use c++11 and g++5.x.
Edit:
The problem that I encountered is because of having an old version of a macro, that it could be used with no restriction, so now I have many parts in my code that uses a macro such as foo(Bar::do), but now I have to generate a function using these names but the function names must be distinctive, so I decided to use macro input parameter as a function name, but I encountered the problem I explained.
This is an example:
void Bar::do(some_parameters)
{
FOO(Bar::do);
}
This is the part of code that I had before, now I want to add a second macro above this part, like this:
FOO2(Bar::do)
void Bar::do(some_parameters)
{
FOO(Bar::do);
}
The both names must be the same, but the FOO2 must generate a function based on the input parameters.
Edit2:
I try here to explain the problem more accurate.
Before, I had a macro like this:
#define FOO(name) \
some codes here
But now I want that have a macro which able to expand as below:
#define FOO2(name) void proper_fcn_name(name)(const string &name){ do the same thing here}
#define FOO(name) proper_fcn_name(name)(#name)
Which I can use that like this:
FOO2(some_name)
void Bar::fcn()
{
FOO(some_name);
}
And if some_name was in the format of Bar::fcn I want that proper_fcn_name changes that to for example Bar_fcn. In final I wish to have something like this, if some_name was Bar::fcn:
void Bar_fcn(const stirng& name) { }
void Bar::fcn()
{
Bar_fcn("Bar::fcn");
}
I must mention that Bar::fcn is just a name but I have to consider this because my library users used this style before.
I was interested by your question and made the following example:
#include <iostream>
#include <string>
using namespace std;
#define foo(name) void name (const string& in) { cout << in << endl; }
// function with name bar_do
foo(bar_do)
// function with name bar_do
foo(do_bar)
int main(void)
{
bar_do("The first test");
do_bar("The second test");
}
In fact it works (it is the output),
The first test
The second test
but I cannot understand what do you want from that strange usage of macro definition - now that looks like automatic copy-paste approach for producing identical functions with different names.
UPDATE
If you really want to use namespace (e.g. Bar) consider the following example:
#include <iostream>
#include <string>
using namespace std;
#define foo(name) void name (const string& in) { cout << in << endl; }
namespace Bar{
void func(const string& in);
}
foo(Bar::func)
int main(void)
{
Bar::func("The special test");
}
You should understand, that namespace have to be defined, and do is keyword of C++ language (so, you should not use it as function name)
UPDATE 2
If it is possible to change FOO(Bar::do); to FOO(Bar,do); in your old code, you can do simple substitution to generate Bar_do identifiers for call and for definition:
#include <iostream>
#include <string>
using namespace std;
#define defgen(class_name,method_name) void class_name##_##method_name(const string& in) { cout << in << endl; }
#define callgen(class_name,method_name,...) class_name##_##method_name(__VA_ARGS__);
// produses definition
defgen(Bar,do)
int main(void)
{
// produces call with particular value as an argument
callgen(Bar,do,"The call test");
}
kfsone said (in comments to your question):
MYMACRO(A::b) might produce A_b_stub
but unfortunately I do not know how (and suppose that it is impossible) to do replacement of :: with other characters (e.g. _).
I don't think it can be stressed enough that you should not do this and this sounds like there's an XY problem here.
You should probably explain the problem in full, why are you trying to generate this function, how is it used, etc.
Anyway enough preaching, here's a work-around:
#include <iostream>
#include <map>
#include <string>
#include <functional>
std::map<std::string, std::function<void(const std::string&)>> g_functions;
#define FOO(name) static void* nonsense##__COUNTER__ = \
(void*)&( g_functions[ #name ] = \
[](const std::string& in) \
{ \
std::cout << "generated function for : " << #name \
<< " called with arg:" << in << std::endl; \
});
#define FOO2(name) {g_functions[ #name ](#name); }
namespace Bar
{
FOO(Bar::func)
void func()
{
FOO2(Bar::func);
}
}
int main() {
Bar::func();
return 0;
}
If your compiler doesn't have __COUNTER__ you can sort of use __LINE__ most of the time (what is one more ugly hack on top of this pile).
I am taking a class next week on C++11/14 and need to verify that my design tools are up to date and can actually compile C++11/14.
What is the simplest piece of code that I can put together to verify that I can actually compile and execute C++11/14 code on my Linux box? I know I need GCC 4.9.X or better, but I want to just be sure that everything is jiving before I show up.
Thanks for the help.
You can initially compile with -std=c++14. If your gcc (or clang) is not c++14 compliant then compilation will fail (due to uknown flag) :
g++: error: unrecognized command line option '-std=c++14'
Regarding feature availability (querying the existence of specific features), you can perform feature testing. An example document can be found here : it all boils down to the use of macros to test the availability of the specified feature (therein you can also find what features to look for).
So even if you want to build with several compilers you can write code like this (naive example follows) :
#if __cpp_constexpr
constexpr
#endif
int triple(int k) { return 3*k; } // compiles with c++98 as well
which is how cross platform developing overcomes the joys of supporting multiple compilers and their versions (more elaborate examples would show supporting sth one way in gcc and another way in cl due to different speed of standard implementation)
The __cplusplus macro contains the C++ standard that the compiler is using. Each version of C++ has a specific value for this define. These may (counter intuitively) not match exactly with the name of the standard, so you can use gcc to determine what the values are. For example:
#include <stdio.h>
int main()
{
printf("%ld\n", __cplusplus);
}
Compiled like so:
g++ -std=c++98 file.cpp
g++ -std=c++11 file.cpp
g++ -std=c++14 file.cpp
Gives the following respectively when run:
199711
201103
201300
You can then use the predefined macros to generate errors if the value you're looking for isn't available. For example:
#if __cplusplus < 201300
#error I require C++14 for this code, so die.
#endif
// ...
Then g++ -std=c++11 file.cpp will fail compilation.
To be sure it works you can simple try to compile some code available only since c++14. For example
#include <iostream>
#include <tuple>
#include <functional>
auto f() // this function returns multiple values
{
int x = 5;
return std::make_tuple(x, 7); // not "return {x,7};" because the corresponding
// tuple constructor is explicit (LWG 2051)
}
int main()
{
// heterogeneous tuple construction
int n = 1;
auto t = std::make_tuple(10, "Test", 3.14, std::ref(n), n);
n = 7;
std::cout << "The value of t is " << "("
<< std::get<0>(t) << ", " << std::get<1>(t) << ", "
<< std::get<2>(t) << ", " << std::get<3>(t) << ", "
<< std::get<4>(t) << ")\n";
// function returning multiple values
int a, b;
std::tie(a, b) = f();
std::cout << a << " " << b << "\n";
}
If this does work than you have the right setup :D Hope this helps
Compiling with flag -std=c++11 or -std=c++14 as per Nikos answer can determine if the compiler supports these standards.
Small examples using C++11 and C++14:
For C++11, you could try compiling auto with -std=c++11:
#include <memory>
using namespace std;
int main()
{
auto p1 = make_shared<int>(42);
// use p1
}
For C++14, try using auto as return type with -std=c++14:
auto func(int i)
{
return [i=std::move(i)](int b){return b+i;};
}
int main()
{
int num = func(3)(5);
// use num
}
I'm trying to wrap an existing 3rd party C++ library to a C interface, so that it can be used in bindings for another language. I'm having trouble figuring out how to wrap a namespaced enum, as opposed to just redefining it:
// Existing C++ 3rd party library header
namespace foo {
enum Fruit {
APPLE = 0,
ORANGE
}
}
So then I have my wrapped.{h,cpp} with an extern "C" block, and I just can't figure out how to export the foo::Fruit enum into the C interface
// wrapped.h
#ifdef __cplusplus
extern "C" {
#endif
// I don't want to do this
typedef enum Fruit {
APPLE = 0,
ORANGE
} Fruit;
#ifdef __cplusplus
}
#endif
#endif
Is it possible to export (mirror) foo::Fruit from the C++ library into my C wrapper as Fruit?
edit: I just noticed that you wanted to wrap an existing library without modifying it.
I fear you are about out of luck then. In general there is just no way of extracting just the enum members out of C++ code without the C compiler choking.
In practice you've got the choice whether to programmatically translate your own set of enumerations into the C++ versions in the interface, try to mirror the C++ exactly and place a bunch of static assertions to double-check, or in theory even filtering them out through scripts.
There are simply no good options here I'm afraid. For the record I would tend to prefer the first of these bad options.
Personally I probably would be lazy and just stick to the C version.
Still, if required and the number of constants is large you can do a bit of macro magic to get a single definition with C-style "namespaces" as required.
First a single header defining all enum entries through a macro:
/* Fruit.h */
FOO_ENUM(APPLE) = 0,
FOO_ENUM(ORANGE)
Then in the C header:
/* C interface */
typedef enum {
# define FOO_ENUM(id) FOO_##id
# include "Fruit.h"
# undef FOO_ENUM
} Foo_Fruit_t;
And finally in the C++ header:
// C++ interface
namespace Foo {
enum Fruit_t {
# define FOO_ENUM(id) id
# include "Fruit.h"
# undef FOO_ENUM
};
}
There are many alternatives of course. For instance if you don't mind polluting the global namespace in C++ then can always define the full enumeration directly in the C interface and copy the individual enum members in the C++ version of the definition.
I ran into this particular problem with enums in a C wrapper for a C++ library recently and it caused quite a headache.
My solution is shown in the following mostly minimal working example but it is terribly inelegant in places. It is essentially a translation approach.
One must be wary not to declare anything twice with regard to the enums. The example passes int, a string or array of char and an enum.
A library header written in C++. This is the library that will be wrapped. MyClass.h:
#ifndef __MYCLASS_H
#define __MYCLASS_H
#include <iostream>
namespace MyNamespace {
using namespace std;
enum EnumControlInterface {HIDController=1, UVCController=2};
class MyClass {
private:
int m_i;
string m_text;
EnumControlInterface _controller;
public:
MyClass(int val);
~MyClass();
void int_set(int i);
void string_set(string text);
int int_get();
string string_get();
void writeEnum(EnumControlInterface MyInterface);
EnumControlInterface readEnum();
};
};
#endif
The C++ implementation of MyClass.cpp:
#include "MyClass.h"
namespace MyNamespace {
MyClass::MyClass(int val) {
cout << "MyClass is being created" << endl;
cout << "The parameter passed to the MyClass constructor is: " << val << endl;
}
MyClass::~MyClass() {
cout << "MyClass is being destroyed" << endl;
}
void MyClass::writeEnum(EnumControlInterface MyInterface) {
_controller = MyInterface;
cout << "The interface control Enum is set in MyClass.cpp as: " << _controller << endl;
}
EnumControlInterface MyClass::readEnum() {
return _controller;
}
void MyClass::string_set(std::string text) {
m_text = text;
}
string MyClass::string_get() {
return m_text;
}
void MyClass::int_set(int i) {
m_i = i;
}
int MyClass::int_get() {
return m_i;
}
}
A "C wrapper" header file MyWrapper.h which wraps MyClass.h:
#ifndef __MYWRAPPER_H
#define __MYWRAPPER_H
#ifdef __cplusplus
namespace MyNamespace {
extern "C" {
#endif
typedef enum WrapperEnumControlInterface {WrapHIDController=1, WrapUVCController=2} WrapperEnumControlInterface;
typedef struct MyClass MyClass;
MyClass* newMyClass(int val);
void MyClass_int_set(MyClass* v, int i);
int MyClass_int_get(MyClass* v);
void MyClass_string_set(MyClass* v, char* text);
char* MyClass_string_get(MyClass* v);
void MyClass_writeEnum(MyClass* v, WrapperEnumControlInterface MyInterface);
WrapperEnumControlInterface MyClass_readEnum(MyClass* v);
void deleteMyClass(MyClass* v);
#ifdef __cplusplus
}
}
#endif
#endif
The "C wrapper" implementation is written in a mixture of C and C++. Specifically the function definitions have to be C and the parameters passed and returned have to be C types as well. Inside the functions and inside the preprocessor areas __cplusplus C or C++ should be fine.
One can not, for example, ask a function inside the extern "C" block to accept the type std::string. It would defeat the objective of the wrapper: to expose only C code that operates the underlying C++ library. extern "C" determines what is exposed without name mangling (see questions about name mangling in C++). __cplusplus is defined by (many) C++ compilers.
MyWrapper.cc:
#include "MyClass.h"
#include "MyWrapper.h"
#include <vector>
namespace MyNamespace {
extern "C" {
MyClass* newMyClass(int val) {
return new MyClass(val);
}
void deleteMyClass(MyClass* v) {
delete v;
}
void MyClass_int_set(MyClass* v, int i) {
v->int_set(i);
}
int MyClass_int_get(MyClass* v) {
return v->int_get();
}
void MyClass_string_set(MyClass* v, char* text) {
//convert incomming C char* to a C++ string
string stringToSend = string(text);
cout << "the string received from the program by the wrapper is " << text << endl;
cout << "the string sent to the library by the wrapper is " << stringToSend << endl;
v->string_set(stringToSend);
}
char* MyClass_string_get(MyClass* v) {
string result = v->string_get();
cout << "the string received from the library by the wrapper is " << result << endl;
// Convert the C++ string result to a C char pointer and return it. Use vectors to do the memory management.
// A vector type of as many chars as necessary to hold the result string
static vector<char> resultVector(result.begin(), result.end());
cout << "the data in the vector who's pointer is returned to the program by the wrapper is: " << &resultVector[0] << endl;
return (&resultVector[0]);
}
void MyClass_writeEnum(MyClass* v, WrapperEnumControlInterface MyInterface) {
v->writeEnum((EnumControlInterface)MyInterface);
}
WrapperEnumControlInterface MyClass_readEnum(MyClass* v) {
EnumControlInterface result = v->readEnum();
return (WrapperEnumControlInterface)result;
}
}
}
A C program that calls the C++ library via the wrapper Cproject.c:
#include "MyWrapper.h"
#include "stdio.h"
int main(int argc, char* argv[]) {
struct MyClass* clsptr = newMyClass(5);
MyClass_int_set(clsptr, 3);
printf("The int read back in Cproject.c is: %i\n", MyClass_int_get(clsptr));
MyClass_writeEnum(clsptr, WrapUVCController);
printf("The enum read back in Cproject.c is: %d\n", MyClass_readEnum(clsptr));
MyClass_string_set(clsptr, "Hello");
char *textReadBack = MyClass_string_get(clsptr);
printf("The text read back in Cproject.c is: %s \n", textReadBack);
deleteMyClass(clsptr);
return 0;
}
And just for completeness a C++ project that calls the C++ library directly without the use of the wrapper CPPProgram.cpp, so short!:
#include "MyClass.h"
#include <iostream>
using namespace std;
using namespace MyNamespace;
int main(int argc, char* argv[]) {
MyClass *c = new MyClass(42);
c->int_set(3);
cout << c->int_get() << endl;
c->writeEnum(HIDController);
cout << c->readEnum() << endl;
c->string_set("Hello");
cout << c->string_get() << endl;
delete c;
}
The MyClass C++ class is compiled to a static library, the wrapper is compiled to a shared library there is no particular reason, both could be static or shared.
The C program that calls the wrapper library (Cproject.c) must be linked with a C++ compiler (G++ etc.)
Obviously this example doesn't have a serious application. It is based on https://www.teddy.ch/c++_library_in_c/ in terms of structure but with the enum bits added in.
Often the person writing the wrapper doesn't have access to the source code of the library they're trying to wrap (MyClass.cpp in this case) they will have the .so or .dll or .a or .lib for Linux and Windows shared and static libraries respectively. It is not necessary to have the source code for the C++ library. Only the header file(s) for the C++ library are needed to write an effective wrapper.
I have written this out partly to provide a more verbose answer to the original question, one that can be copied compiled easily and played around with but also because this is the only way I have been able to solve the problem so far and it is not satisfactory in my view. I would like to be able to wrap the enums in the same way one wraps the public member functions not re-create the enums inside the wrapper with slightly different names.
Sources of related information that proved useful:
https://www.teddy.ch/c++_library_in_c/
How to cast / assign one enum value to another enum
Developing C wrapper API for Object-Oriented C++ code
Converting a C-style string to a C++ std::string
Returning pointer from a function
std::string to char*
Of course all unsafe, wrong etc. coding practices are my fault entirely.
The following code compiles fine on Windows with Visual Studio:
class_handle(base *ptr) : ptr_m(ptr), name_m(typeid(base).raw_name()) { signature_m = CLASS_HANDLE_SIGNATURE; }
If I try to compile the same code on Linux I get:
error: ‘const class std::type_info’ has no member named ‘raw_name’
as far as I understand, raw_name is a Microsoft specific implementation. How do I have to change my code so it compiles both on Windows and Linux systems?
EDIT1 I prefer to not modify the original code, I just need a workaround to compile with gcc. Is that possible?
EDIT2 will #define raw_name name do the trick?
Write these:
// for variables:
template<typename T>
char const* GetRawName( T unused ) { ... }
// for types:
template<typename T>
char const* GetRawName() { ... }
with different implementation on Windows and not-on-Windows using an #ifdef block on a token you know to be defined in the microsoft compiler, but not in your other compiler. This isolates the preprocessing differences between MS and non-MS compiled versions to an isolated file.
This does require a minimal amount of change to the original code, but does so in a way that will still compile on the microsoft compiler.
It's probably safer to #define typeid:
class compat_typeinfo {
const std::type_info &ti;
public:
explicit compat_typeinfo(const std::type_info &ti): ti(ti) {}
const char *name() const { return ti.name(); }
const char *raw_name() const { return ti.name(); }
};
compat_typeinfo compat_typeid(const std::type_info &ti) {
return compat_typeinfo(ti);
}
#define typeid(x) compat_typeid(typeid(x))
Of course, this is illegal by 17.6.4.3.1p2 (A translation unit shall not #define or #undef names lexically identical to keywords [...]) but it's reasonably likely to work and requires minimal modification elsewhere.
GCC doesn't define raw_name but does include mangling/demangling in cxxabi.h. You can see an example of it here.
#include <cxxabi.h>
//...
std::bad_exception e;
realname = abi::__cxa_demangle(e.what(), 0, 0, &status);
std::cout << e.what() << "\t=> " << realname << "\t: " << status << '\n';
free(realname);
Following code fails with a error message :
t.cpp: In function `void test()':
t.cpp:35: error: expected primary-expression before '>' token
t.cpp:35: error: expected primary-expression before ')' token
Now I don't see any issues with the code and it compiles with gcc-4.x and MSVC 2005 but not with gcc-3.4 (which is still quite popular on some platforms).
#include <string>
#include <iostream>
struct message {
message(std::string s) : s_(s) {}
template<typename CharType>
std::basic_string<CharType> str()
{
return std::basic_string<CharType>(s_.begin(),s_.end());
}
private:
std::string s_;
};
inline message translate(std::string const &s)
{
return message(s);
}
template<typename TheChar>
void test()
{
std::string s="text";
std::basic_string<TheChar> t1,t2,t3,t4,t5;
t1=translate(s).str<TheChar>(); // ok
char const *tmp=s.c_str();
t2=translate(tmp).str<TheChar>(); // ok
t3=message(s.c_str()).str<TheChar>(); // ok
t4=translate(s.c_str()).str<TheChar>(); // fails
t5=translate(s.c_str()).template str<TheChar>(); // ok
std::cout << t1 <<" " << t2 <<" " << t3 << " " << t4 << std::endl;
}
int main()
{
test<char>();
}
Is it possible to workaround it on the level of translate function and message class, or maybe my code is wrong, if so where?
Edit:
Bugs related to template-functions in GCC 3.4.6 says I need to use keyword template but should I?
Is this a bug? Do I have to write a template keyword? Because in all other cases I do not have to? And it is quite wired I do not have to write it when I use ".c_str()" member function.
Why gcc-4 not always an option
This program does not starts when compiled with gcc-4 under Cygwin
#include <iostream>
#include <locale>
class bar : public std::locale::facet {
public:
bar(size_t refs=0) : std::locale::facet(refs)
{
}
static std::locale::id id;
};
std::locale::id bar::id;
using namespace std;
int main()
{
std::locale l=std::locale(std::locale(),new bar());
std::cout << has_facet<bar>(l) << std::endl;
return 0;
}
And this code does not compiles with gcc-4.3 under OpenSolaris 2009- broken concepts checks...
#include <map>
struct tree {
std::map<int,tree> left,right;
};
As mentioned elsewhere, that seems to be a compiler bug. Fair enough; those exist. Here's what you do about those:
#if defined(__GNUC__) && __GNUC__ < 4
// Use erroneous syntax hack to work around a compiler bug.
t4=translate(s.c_str()).template str<TheChar>();
#else
t4=translate(s.c_str()).str<TheChar>();
#endif
GCC always defines __GNUC__ to the major compiler version number. If you need it, you also get __GNUC_MINOR__ and __GNUC_PATCHLEVEL__ for the y and z of the x.y.z version number.
This is a bug in the old compiler. Newer GCC's, from 4.0 to (the yet unreleased) 4.5, accept it, as they should. It is standard C++. (Intel and Comeau accept it also.)
Regarding cygwin and opensolaris, of course gcc-3.4 is not the only option: the newer versions (the released 4.4.3, or the unreleased 4.5 branch) work fine on these OS'es. For cygwin, it's part of the official distribution (see the gcc4* packages in the list). For opensolaris, you can compile it yourself (and instructions on how to do so can easily be found with Google).
I would try to use a different workaround, since adding the template disambiguator there is incorrect and will break if you move to a different compiler later on.
I don't know the real code, but passing a regular std::string seems to work (option 1: avoid converting to const char * just to create a temporary) or you could provide an overloaded translate that takes a const char* as argument (if the compiler does not complain there), depending on your requirements.