#define equivalent in c++ - c++

g++ 4.7.2
Hello,
I am coming from C89 and now I am doing c++ using g++ compiler.
Normally I do things like this:
#define ARR_SIZE 64
#define DEVICE "DEVICE_64"
What is the equivalent of doing this in C++?
Many thanks for any suggestions,

#define is there in C++. So you can write the same code. But for constant quantities like this, it is better to use the const keyword.
const int ARR_SIZE = 64;
const std::string DEVICE("DEVICE_64");

You can use const in place of #define
const int ARR_SIZE = 64;
const char DEVICE[] = "DEVICE_64";

You can define constants using the const keyword:
const int ARR_SIZE = 64;
const char DEVICE[] = "DEVICE_64";

It’s even better to use anonymous namespace for that (restricted to current file):
namespace {
int const ARR_SIZE = 64;
/* ... */
}

#define is fine !
Excepting type checking, most of C code compile without change with a C++ compiler. So #define is still valid in C++.
you might want to take a look to other stackoverflow entries like :
Should I use #define, enum or const?
What issues can I expect compiling C code with a C++ compiler?

Related

Type punning in C++ via extern "C" function using union

The ubiquitous problem of converting contiguous bytes into other typed objects can be solved in C using unions. This is not possible in C++ due the active-member definition.
Therefore, in the following snippet the actual "punning" is done by a C-function. I wonder if this is correct? This for sure depends on the meaning of the "extern" keyword.
#include <cstdint>
#include <cstddef>
#include <string.h>
namespace Util {
namespace detail {
union Punn {
std::byte small[sizeof(uint32_t)];
uint32_t big;
};
}
extern "C" {
inline uint32_t read(const Util::detail::Punn* u) {
return u->big;
}
}
}
int main() {
Util::detail::Punn a;
a.small[0] = std::byte{1};
a.small[1] = std::byte{2};
a.small[2] = std::byte{3};
a.small[3] = std::byte{4};
auto x = Util::read(&a);
return x;
}
I know that the two real save solutions the this problem are shifts or memcpy(). So, please only argue about the above code using extern "C" function. (Aside: the generated assembler code is correct on g++, but that doesn't mean, that it is strictly conforming.)

extern const std::string not initialized under iOS, works fine on Windows

I have a Configurations.h and Configurations.cpp that define some constant string values that are used everywhere in my cross-platform application.
In another file I use some of these values to create other constant strings.
That could look like this:
const std::string SHADER_SOURCE_HEAD_ES = Configurations::DEFAULT_SHADER_VERSION_ES + SHADER_SOURCE_LINE_BREAK + "precision mediump float" + SHADER_SOURCE_LINE_ENDING;
This works fine on Windows and it worked on iOS as well before I changed everything to be "extern const" in Configurations.h and did the declaration in the cpp-File.
Now on iOS Configurations::DEFAULT_SHADER_VERSION_ES is empty. Configuration.h is of course included first, so the constants should exist (and do on Windows). I also have some functions that use the constants (in the same file as const std::string SHADER_SOURCE_HEAD_ES) and there they work.
What could be wrong here? Thank you so much guys :-)
Sounds like it's an order of initialization issue. A cleaner approach would be to use functions to provide access to those strings. In those functions, make the variable static and initialize them appropriately.
For example, instead of using:
extern const int myVar;
in the .h file and
const int myVar = 20;
in the .cpp file, use:
extern int getMyVar();
in the .h file and
int getMyVar()
{
static const int myVar= 20;
return myVar;
}
in the .cpp file.

Xerces-c and cross-platform string literals

I'm porting a code-base that uses Xerces-c for XML processing from Windows/VC++ to Linux/G++.
On Windows, Xerces-c uses wchar_t as the character type XmlCh. This has allowed people to use std::wstring and string literals of L"" syntax.
On Linux/G++, wchar_t is 32-bit and Xerces-c uses unsigned short int (16-bit) as the character type XmlCh.
I've started out along this track:
#ifdef _MSC_VER
using u16char_t = wchar_t;
using u16string_t = std::wstring;
#elif defined __linux
using u16char_t = char16_t;
using u16string_t = std::u16string;
#endif
Unfortunately, char16_t and unsigned short int are not equivalent and their pointers are not implicitly convertible. So passing u"Hello, world." to Xerces functions still results in invalid conversion errors.
It's starting to look like I'm going to have to explicitly cast every string I pass to Xerces functions. But before I do, I wanted to ask if anyone knows a saner way to programme cross-platform Xerces-c code.
The answer is that no, no-one has a good idea on how to do this. For anyone else who finds this question, this is what I came up with:
#ifdef _MSC_VER
#define U16S(x) L##x
#define U16XS(x) L##x
#define XS(x) x
#define US(x) x
#elif defined __linux
#define U16S(x) u##x
#define U16XS(x) reinterpret_cast<const unsigned short *>(u##x)
inline unsigned short *XS(char16_t* x) {
return reinterpret_cast<unsigned short *>(x);
}
inline const unsigned short *XS(const char16_t* x) {
return reinterpret_cast<const unsigned short *>(x);
}
inline char16_t* US(unsigned short *x) {
return reinterpret_cast<char16_t *>(x);
}
inline const char16_t* US(const unsigned short *x) {
return reinterpret_cast<const char16_t*>(x);
}
#include "char16_t_facets.hpp"
#endif
namespace SafeStrings {
#if defined _MSC_VER
using u16char_t = wchar_t;
using u16string_t = std::wstring;
using u16sstream_t = std::wstringstream;
using u16ostream_t = std::wostream;
using u16istream_t = std::wistream;
using u16ofstream_t = std::wofstream;
using u16ifstream_t = std::wifstream;
using filename_t = std::wstring;
#elif defined __linux
using u16char_t = char16_t;
using u16string_t = std::basic_string<char16_t>;
using u16sstream_t = std::basic_stringstream<char16_t>;
using u16ostream_t = std::basic_ostream<char16_t>;
using u16istream_t = std::basic_istream<char16_t>;
using u16ofstream_t = std::basic_ofstream<char16_t>;
using u16ifstream_t = std::basic_ifstream<char16_t>;
using filename_t = std::string;
#endif
char16_t_facets.hpp has definitions of the template specialisations std::ctype<char16_t>, std::numpunct<char16_t>, std::codecvt<char16_t, char, std::mbstate_t>. It's necessary to add these to the global locale, along with std::num_get<char16_t> and std::num_put<char16_t> (but it's not necessary to provide specialisations for these). The code for codecvt is the only bit that's difficult, and a reasonable template can be found in the GCC 5.0 libraries (if you use GCC 5, you don't need to provide the codecvt specialisation as it's already in the library).
Once you've done all of that, the char16_t streams will work correctly.
Then, every time you define a wide string, instead of L"string", write U16S("string"). Every time you pass a string to Xerces, write XS(string.c_str()) or U16XS("string") for literals. Every time you get a string back from Xerces, convert it back as u16string_t(US(call_xerces_function())).
Note that it is also possible to recompile Xerces-C with the character type set to char16_t. This removes a lot of the effort required above. BUT you won't be able to use any other library on the system that in turn depends on Xerces-C. Linking to any such library will cause link errors (because changing the character type changes many of the Xerces function signatures).

How to count number of macro execution?

I have two macros that declares class properties:
DECLARE_QUERY_PARAM_LONG(name)
DECLARE_QUERY_PARAM_STRING(name)
I want to count number of calls of this macros inside of my class and init
static const size_t paramsCount
with that number like this:
class MyClass {
...
DECLARE_QUERY_PARAM_LONG(param1)
DECLARE_QUERY_PARAM_STRING(param2)
DECLARE_QUERY_PARAM_STRING(param3)
DECLARE_QUERY_PARAM_LONG(param4)
static const size_t paramsCount = PARAMS_COUNT; // 4 in this case
...
};
Is this ever possible?
There would be a solution, rather complicated:
All your parameters will have a fixed name (say param)
You need to create one header file per type
You shall need boost
So here is the header creation file:
// file declare_int.h
#include BOOST_PP_UPDATE_COUNTER()
int stringize(param,BOOST_PP_COUNTER) ;
and the class file:
//file declare_auto.cpp
#include <boost/preprocessor/slot/counter.hpp>
#define _stringize(a,b) a##b
#define stringize(a,b) _stringize(a,b)
// reset counter
#if defined(BOOST_PP_COUNTER)
#undef BOOST_PP_COUNTER
#endif
class A {
public:
#include "declare_int.h"
#include "declare_int.h"
#include "declare_int.h"
#include "declare_int.h"
static const int nbParams = BOOST_PP_COUNTER ;
};
and finally the output of:
g++ -E -P -c declare_auto.cpp -IPATH_TO_BOOST
is
class A {
public:
int param1 ;
int param2 ;
int param3 ;
int param4 ;
static const int nbParams = 4 ;
};
You can at least count number of lines in the following way:
class MyClass
{
static const int line_1 = __LINE__;
DECLARE_QUERY_PARAM_LONG(param1)
DECLARE_QUERY_PARAM_STRING(param2)
DECLARE_QUERY_PARAM_STRING(param3)
DECLARE_QUERY_PARAM_LONG(param4)
static const int line_2 = __LINE__;
static const int macro_calls = line_2 - line_1 - 1;
public:
MyClass()
{
cout << macro_calls << endl;
}
};
But I think you'll need C++11 to do that. And You cannot have empty lines within those two __LINE__s. Otherwise, you'll have to count those empty lines as well.
As such no.
What you are asking for would require some form of introspection, which is not natively supported by C++.
You can improve the macro though, if you had:
DECLARE_QUERY_PARAMS(((LONG , param1))
((STRING, param2))
((STRING, param3))
((LONG , param4)))
then you could do what you want.
You can have a look at Boost.Preprocessor to learn how to obfuscate your sources this way.
Note: this uses a Sequence, in boost parlance.
I don't think there's a standard way to do this, but the DevStudio compiler has this preprocessor macro:
__COUNTER__
Expands to an integer starting with 0 and incrementing by 1 every time it is used in a compiland. __COUNTER__ remembers its state when using precompiled headers. If the last __COUNTER__ value was 4 after building a precompiled header (PCH), it will start with 5 on each PCH use.
__COUNTER__ lets you generate unique variable names. You can use token pasting with a prefix to make a unique name. For example:
// pre_mac_counter.cpp
#include <stdio.h>
#define FUNC2(x,y) x##y
#define FUNC1(x,y) FUNC2(x,y)
#define FUNC(x) FUNC1(x,__COUNTER__)
int FUNC(my_unique_prefix);
int FUNC(my_unique_prefix);
No. Macro's don't respect scope at all, and don't understand that they're inside a class.
No. Macros aren't executed, they're expanded and not even by compiler, but by preprocessor.

Question about variables with combination of extern and const

I googled const + extern on the internet, but it seems there isn't really a good answer for my question.
const alone means internal linkage, but if I want to share a const variable among compilation units. Is extern the best choice?
Common solution would be:
//g.h
extern const int MAX;
// g.c
extern const int MAX = 3;
However, this solution has a drawback, like below:
// Say, I want to use this MAX in the same header file.
// g.h
extern const int MAX;
class AClass
{
public:
AClass (): i(MAX){}
private:
int i;
};
Compiler will complain like:"error C2057: expected constant expression".
Is there a solution for this?
if you want to be able to use your constant at compile time (i.e. size an array by it, without using VLA) it has to be known at compile time, i.e. it cannot have external linkage.
However, you could just declare your constant in your header file, and make it available to anyone including it. Still, that won't have the exact same effect as an external linkage.
// a.h
const int MAX = 3;
// a.cpp
#include "a.h"
int b[a];
An easy solution for constant integers is to use enums:
// g.h
enum { MAX = 3; }
// g.c
#include "g.h"
static char buf[MAX];
You won't be able to take the address of MAX, but in turn you get this at zero memory cost.
extern const int MAX;
int i[MAX];
Can't be done. You could do something like
const int MAX = ReadAnIntegerFromTheConsole();
Perfectly valid and legal, but whoopsies- not a constant expression.
const alone means internal linkage
This is not correct, static indicates internal linkage, const just says the object cannot mutate. Try declaring a variable as
extern static int foo;
Your compiler will complain about conflicting linkage. To share a const between translation units do exactly what you've suggested.
In the header
extern const int MAX;
In the source file
const int MAX = 10; // note you can omit the extern here
Here is a working example that may solve your issue. In summary, define the array size as a constant in a header file. In another header file declare the array as extern. In the example below I reference the array as extern without using an include file for the array.
array_size.hpp
const unsigned int MAX_ARRAY_SIZE = 16;
array.cpp
#include "array_size.hpp"
int array[MAX_ARRAY_SIZE];
main.cpp
#include "array_size.hpp"
// Reference the array from array.cpp
extern int array[MAX_ARRAY_SIZE];
int main(void)
{
array[1] = 7;
return 0;
}
The *array_size.hpp* file defines the size, the identifier can be used in other translation units by including the header.
I compiled on Cygwin using:
g++ -I. -o array.exe main.cpp array.cpp
Why not just use a #define?
#define MAX 3