C++: Define simple constant for use? - c++

In C++ I wanted to define a constant that I can use in another function, A short answer on how to do this will be fine..
Lets say at the beginning of my code I want to define this constant:
//After #includes
bool OS = 1; //1 = linux
if (OS) {
const ??? = "clear";
} else {
const ??? = "cls";
}
I don't know what type to use to define the "clear" string... I'm so confused.
Later on I want to use it within a function:
int foo() {
system(::cls); //:: for global
return 0;
}
How would I define the string up top, and use the string down below? I heard char only had one character and things... I'm not sure how to use , since it says it's converting string into const char or something.

char* isn't quite a char. char* is basically a string (it's what strings were before C++ came along).
For illustration:
int array[N]; // An array of N ints.
char str[N]; // An array of N chars, which is also (loosely) called a string.
char[] degrades to char*, so you'll often see functions take a char*.
To convert std::string to const char*, you can simply call:
std::string s;
s.c_str()
In this case, it's common to use the preprocessor to define your OS. This way you can use the compiler to do the platform specific stuff:
#ifdef OS_LINUX
const char cls[] = "clear";
#elif OS_WIN
const char cls[] = "cls";
#endif
One thing you may want to consider is making it a function. This avoids nasty dependencies of global construction order.
string GetClearCommand() {
if (OS == "LINUX") {
return "clear";
} else if (OS == "WIN") {
return "cls";
}
FAIL("No OS specified?");
return "";
}
What it looks like you're trying to do is this:
#include <iostream>
using namespace std;
#ifdef LINUX
const char cls[] = "LINUX_CLEAR";
#elif WIN
const char cls[] = "WIN_CLEAR";
#else
const char cls[] = "OTHER_CLEAR";
#endif
void fake_system(const char* arg) {
std::cout << "fake_system: " << arg << std::endl;
}
int main(int argc, char** argv) {
fake_system(cls);
return 0;
}
// Then build the program passing your OS parameter.
$ g++ -DLINUX clear.cc -o clear
$ ./clear
fake_system: LINUX_CLEAR

Here's the problem, you're suffering from going out of scope with the variables. If I declare something within brackets, it only exists within the brackets.
if( foo ){
const char* blah = "blah";
}
Once we leave the if statement, the variable blah disappears. You'll need to instantiate it non-locally to whatever brackets you write. Hence:
void Bar(){
const char* blah = "blah";
if( foo ){
//blah exists within here
}
}
However, blah will not exist outside of Bar. Get it?

Yet another option is to create a class with a bunch of static methods. Create a new method for each command. Something like:
// in sys-commands.h
class SystemCommands {
public:
static char const* clear();
static char const* remove();
};
This gives you a few nice options for the implementation. The nicest one is to have a separate implementation file for each platform that you select during compile time.
// in sys-commands-win32.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "cls"; }
char const* SystemCommands::remove() { return "erase /f/q"; }
// in sys-commands-macosx.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "/usr/bin/clear"; }
char const* SystemCommands::remove() { return "/bin/rm -fr"; }
Which file gets compiled will determine which command set will be used. Your application code will look like:
#include <cstdlib>
#include "sys-commands.h"
int main() {
std::system(SystemCommands::clear());
return 0;
}
Edit: I forgot to mention that I prefer static functions to global constants for a bunch of reasons. If nothing else, you can make them non-constant without changing their types - in other words, if you ever have to select the command set based on runtime settings, the user code does not have to change or even be aware that such a change occurred.

You can use a common header file and link to different modules depending on the systen:
// systemconstants.hpp
#ifndef SYSTEM_CONSTANTS_HPP_INCLUDED
#define SYSTEM_CONSTANTS_HPP_INCLUDED
namespace constants {
extern const char cls[]; // declaration of cls with incomplete type
}
#endif
In case of Linux, just compile and link to this one:
// linux/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "clear";
}
In case of Windows, just compile and link to this one:
// windows/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "cls";
}
System-specific translation units could be placed in specific subdirectories (linux/, windows/, etc) of which one could be automatically selected during the build process. This extends to many other things, not just string constants.

Related

c++ runtime dispatch of 2 sets of static constants

Motivation
A CLI app tries to make use of box drawing characters. But depending on the stdout device this may not be appropriate so there is a -t option to use pure ASCII text.
The concept is just an example, this applies anywhere where we want to select from two or more sets of static constants at runtime.
The question is what is reasonable c++ technique to facilitate this cleanly.
Desired usage Syntax
This is indicative only, but it the constant "invocation" should be terse
int main(int argc, char* argv[]) {
// using derived class style here, but anything would do
auto t = std::strcmp(argv[1], "-t") == 0 ? TxtTerminal() : BdTerminal();
// here we want the syntax to be short
std::cout << "text" << t.horiz << t.right_t << '\n';
}
Already tried
I have tried Base and Derived class style (as above) but there are issues. I can't put one set of constants in TxtTerminal and one in BdTerminal (which extends TxtTerminal).
Using static constants doesn't work, because C++ doesn't support "late static binding" , so it always uses the constants of whichever class you have the instance of.
Using member variables and proper instances of those classes (as hinted at above) doesn't work (nicely) either because the Derived class can't initialise the Base class members directly....
Nor via its constructor initialiser list ...
The derived class would have to pass the entire set to the base class constructor which then modifies the already (BaseClass)initialised values. Really awkward and long winded. I guess passing some struct config { .. }; could work
Similarly using a single class, putting both sets of constants in there in a map<key,config> and using a getter to retrieve the appropriate constant using a constructor initialised bool textmode member state variable.
Maybe with a templated solution taking some template parameter? Well no, because this is a runtime switch.
Similar to the template idea would be some kind of solution with using aliases for 2 separate constant namespaces..same problem..compile time..not runtime.
Using variable templates a bit like the new c++20 maths constants . Same problem, not runtime.
Of course all this const, ie strings of the control character for the "box drawing terminal" are just a bytes long each. Ideally these would just be compacted together as literal initialised const char* in the .text (linux) segment of the executable (std::string seems overkill). Wherever we compose these constants we would want easy concatenation to make the code readable and maintainable. That's not so easy with const char* string literals?
Many options, none seem great. Am I missing something obvious?
EDIT In response to questions below and also to the initial answer by #walnut here is some more fleshed out code using the "static non-instance" approach.
Some unsolved problems therein, see comments:
// NOTE this code compiles and runs, but doesn't quite do what we need
// see comments
#include <cstring>
#include <iostream>
struct TextMode {
static inline const auto cls = "TM cls";
static inline const auto right_t = "TM right_t";
static inline const auto left_t = "TM left_t";
};
struct BlockDrawMode {
static inline const auto cls = "BD cls";
static inline const auto right_t = "BD right_t";
static inline const auto left_t = "BD left_t";
};
struct Terminal {
Terminal(bool textmode = true) { mode = textmode ? &text_mode : &block_drawing_mode; }
// what is this type? some parent class of TextMode/BlockDrawMode?!
// then we get the initilisation loop again...
// ??????? // could be a reference initilised in cstr initilisation, but that's a detail
const TextMode* mode;
static inline const auto text_mode = TextMode{};
static inline const auto block_drawing_mode = TextMode{};
// obviously this needs to be .. ^ BlockDrawMode
// but then doesn't compile because there is no class hierarchy ...
};
int main(int argc, char* argv[]) {
Terminal t{strcmp(argv[1], "-t") == 0};
std::cout << t.mode->cls << '\n' << t.mode->right_t << '\n';
// output (-t makes no difference right now, due to the above issues)
// TM cls
// TM right_t
return 0;
}
EDIT2: I have added a self answer below which uses aggregate initialisation to avoid a lot of the unwanted inheritance complications. Feels a bit "dirty", but looks clean and works fine?
From the comments I gather that what you are looking for is:
If there aren't any other differences in behavior requiring a virtual interface or inheritance, then you can just define a pointer member which is chosen for the correct implementation at construction:
struct Terminal {
Terminal(/* parameters */) {
chooseConfig(/* some arguments */);
}
static constexpr char config1[]{/*...*/};
static constexpr char config2[]{/*...*/};
const char* config;
void chooseConfig(/*arguments*/) {
config = /*condition*/ ? config1 : config2;
};
// use `config` everywhere
};
int main(int argc, char* argv[]) {
Terminal terminal{/* arguments */};
//...
}
If all instances of this class are supposed to share the same configuration and passing the arguments to choose the configuration each time is too cumbersome, then you can also make config and chooseConfig static and instead of calling it in the constructor, call it once in main with Terminal::chooseConfig(/*arguments*/);.
A proposed "self answer":
Here is a version that avoids the hierarchy complications of the config structs. Basically aggregate initialization to the rescue...
This final version shows some proper terminal control strings and some tweaks using a ref to static inline struct. plus it uses designated initialisers. Note selective overrides from the Base Struct Config details would be possible if desired. All the "keys" are automatically checked at compile time, so prevent mistakes during maintenance.
struct Mode {
const char* const esc = "";
const char* const cls = "";
const char* const bd_on = "";
const char* const bd_off = "";
const char* const underline_on = "";
const char* const black = "";
const char* const red = "";
const char* const green = "";
const char* const yellow = "";
const char* const blue = "";
const char* const magenta = "";
const char* const cyan = "";
const char* const white = "";
const char* const reset = "";
const char horiz = '-';
const char vert = '|';
const char right_t = '|';
const char left_t = '|';
const char bottom_t = '|';
const char top_t = '|';
const char intersec = '|';
};
struct Terminal {
static inline const Mode text_mode;
// warning: this is a C99 extension until C++20 comes in
// but it nicely compile checks and self documents the code
// supported by gcc4.7, clang3.0 and msvc19.21
static inline const Mode box_draw_mode{
.esc = "\x1b",
.cls = "\x1b[2J",
.bd_on = "\x1b(0",
.bd_off = "\x1b(B",
.underline_on = "\x1b[4m",
.black = "\x1b[30m",
.red = "\x1b[31m",
.green = "\x1b[32m",
.yellow = "\x1b[33m",
.blue = "\x1b[34m",
.magenta = "\x1b[35m",
.cyan = "\x1b[36m",
.white = "\x1b[37m",
.reset = "\x1b[0m",
.horiz = '\x71',
.vert = '\x78',
.right_t = '\x75',
.left_t = '\x74',
.bottom_t = '\x76',
.top_t = '\x77',
.intersec = '\x6e',
};
const Mode& m;
Terminal(bool textmode = true) : m{textmode ? text_mode : box_draw_mode} {}
};
int main(int argc, char* argv[]) {
Terminal t1{true};
Terminal t2{false};
// usage
// std::cout << t1.m.cls << '\n' << t1.m.right_t << '\n';
// std::cout << t2.m.cls << '\n' << t2.m.right_t << '\n';
return 0;
}
Here is a godbolt (note that clang>3 and gcc>4.7 compile the designated initialisers just fine already). Also note that the godbolt shows that on -O3 the initializers get optimized away to the point were the char values just become inlined register loads. On O1 we can clearly see the strings laid out in .text segment and literally the only thing that happen during Terminal construction is the setting of a single pointer for Mode& m to point to one of the 2 structures: mov qword ptr [rdi], rcx. Good?

How to printf() a user class?

The program fails while compiling the code. Compiler points to printf("Version = '%s'\n", gABXVER). I guess that I actually can't write gABXVER = "V1R1", but I don't have any other idea.
class CISPFVar_BINSTR : public CISPFVar
{
protected:
char* m_pBuffer;
long m_bDefined;
public:
...
void Initialize(char* szName, long lSize, int bDefineVar = 1)
{
Uninitialize();
ZStrToCharArray(szName, m_cName, 8);
m_Size = lSize+1;
m_pBuffer = (char*)malloc(m_Size);
m_pBuffer[0] = 0;
if (bDefineVar)
ISPLINK(__VDEFINE, m_cName, m_pBuffer, __BINSTR, &m_Size);
m_bDefined = bDefineVar;
}
...
};
CISPFVar_BINSTR gABXVER;
char szLoadLibraryPath[50];
int main(
int argc,
char* argv[])
{
if (argc > 1)
if (argv[1]) strcpy(szLoadLibraryPath, argv[1]);
gABXVER.Initialize("ABXVER",4);
gABXVER = "V1R1";
printf("Version = '%s'\n", gABXVER);
return 0;
};
When you use %s in printf family of functions, the corresponding argument type needs to be const char* or something that can be converted to const char*. The argument you are using is not such a type. Perhaps you meant to use:
printf("Version = '%s'\n", gABXVER.m_pBuffer);
The compiler should compile just fine (with possible warnings for printf) because printf doesn't care what you pass to it (beyond the first parameter) or whether it matches the format string. Modern compilers or error checking progs like lint will issue a warning if the params obviously don't match, and if you have a setting "treat warnings as errors", the prog may fail to compile.
That said, CISPFVar_BINSTR needs a public copy constructor if you want to pass it as a parameter by value to a function (because at least semantically a copy will be made). Does it have one? As others remarked it's customary to help your helpers by providing any information you have. Here we are badly missing the compiler errors. (You can edit your post at any time.)
I could imagine that the class has a conversion to char* or std::string, so it may suffice to try either printf("Version = '%s'\n", (char *)gABXVER) or printf("Version = '%s'\n", (std::string(gABXVER)).c_str() ).
You can only printf things that have format specifiers designed specifically for them. There is no format specifier that accepts a value of class type, so you cannot printf one directly.
The best thing you can do is explicitly convert your object to a const char* and pass the result to printf.
In c++ you can use many techniques to implement things like streaming operators
#include <iostream>
class Whatever
{
int value = 42;
public:
int Get() const {
return value;
}
friend std::ostream& operator<<(std::ostream&, Whatever const&);
};
std::ostream& operator<<(std::ostream& os, Whatever const& what) {
os << what.Get();
return os;
}
int main() {
Whatever x;
std::cout << x << std::endl;
}
printf is unsafe
In effect, you're doing serialization of your object into a readable string.

How to cast const char* to static const char XY[]?

I'm doing some C# code which is using DLLImport to call a function inside my C++ DLL:
[DllImport("my.dll", EntryPoint = "#16", CallingConvention = CallingConvention.StdCall)]
private static extern void sendstring(string s);
I call it like this in C#:
sendstring("Test1\\0test2\\0");
My C++ DLL needs to create a static const char XY[] = "Test1\0test2\0"; from this, since I need that for calling another DLLs function from inside my c++ DLL like this:
functiontootherdll(sizeof(s),(void*)s);
So my code in C++:
extern "C" {
void MyClass::sendstring( const char *s) {
functiontootherdll(sizeof(s),(void*)s);
}
The problem: It is working, if I define the thing manually inside my C++ DLL like this:
static const char Teststring[] = "Test1\0test2\0";
functiontootherdll(sizeof(Teststring),(void*)Teststring);
but it is not taking the const char *s when calling this from my C# file (it will report different errors from the called other dll).
I would need to know how I can cast the const char *s to something like static const char s[] or such.
As you realize I have little clue about all this, so any help is very welcome!
Alright, I found out a way I think:
I modified my C++ to:
extern "C" {
void MyClass::sendstring( const char *s) {
int le = strlen(s);
char p[256];
strcpy(p,s);
char XY[sizeof(p) / sizeof(*p) + 1];
int o=0;
for (int i = 0; i<le;i++) {
if (p[i] == ';') {
XY[i] = '\0';
} else {
XY[i] = p[i];
}
o++;
}
XY[o] = '\0';
functiontootherdll(sizeof(XY),(void*)XY);
}
Afterwards the function call to
functiontootherdll(sizeof(XY),(void*)XY);
is working fine.
Pls note that I send from my C# code now a string like "Test1;test2;test3;...", trying with the \\0 as separator did not work out. My call with C# is:
sendstring("Test1;test2;test3");
I don't know if this is a smart solution, but at least it is one :)

C++11 Function That Only Accepts String Literals?

I want to write a C++11 function that will only accept string literals as a parameter:
void f(const char* s) { static_assert(s is a string literal); ... }
That is:
f("foo"); // OK
char c = ...;
f(&c); // ERROR: Doesn't compile
string s = ...;
f(s.c_str()); // ERROR: Doesn't compile
etc
Is there anyway to implement this? The signature of the function is open to changes, as is adding the use of macros or any other language feature.
If this is not possible what is the closest approximation? (Can user-defined literals help in anyway?)
If not is there a platform specific way in GCC 4.7 / Linux ?
I think the closest you are going to get is this
template<int N>
void f(const char (&str)[N]){
...
}
It will compile with literals and arrays but not pointers.
An alternative might be to make a GCC extension to check at compile time that your particular function is only called with a literal string.
You could use MELT to extend GCC. MELT is a high-level domain specific language to extend the GCC compiler, and is very well suited for the kind of check you want.
Basically, you would add a new pass inside GCC and code that pass in MELT which would find every gimple which is a call to your function and check that the argument is indeed a literal string. The ex06 example on melt-examples should inspire you. Then subscribe to gcc-melt#googlegroups.com and ask your MELT specific questions there.
Of course, this is not a foolproof approach: the function could be called indirectly thru pointers, and it could e.g. have a partial literal string, e.g. f("hello world I am here"+(i%4)) is conceptually a call with some literal string (e.g. in .rodata segment), but not in the generated code nor in the gimple.
I use this :
// these are used to force constant, literal strings in sqfish binding names
// which allows to store/copy just the pointer without having to manage
// allocations and memory copies
struct _literalstring
{
// these functions are just for easy usage... not needed
// the struct can be empty
bool equal(_literalstring const *other) { return !strcmp((const char *)this, (const char *)other); }
bool equal(const char *other) { return !strcmp((const char *)this, other); }
const char *str(void) { return (const char *)this; }
bool empty(void) { return *(const char *)this == 0; }
};
typedef _literalstring *LITSTR;
constexpr LITSTR operator "" _LIT(const char *s, size_t) {
return (LITSTR)s;
}
Then you just declare your function like this :
void myFunc(LITSTR str)
{
printf("%s\n", str->str());
printf("%s\n", (const char *)str);
const char *aVar = str->str();
const char *another = (const char *)str;
}
And you call it like this:
myFunc("some text"_LIT);
If you do something like this:
myFunc("some text");
myFunc(aTextVariable);
you get a compiler error.

avoiding global variables while using GLUT

GLUT is a great API and it's very easy to use but I am having some difficulty with how it handles scope. When defining callbacks there is no option to pass parameters so it seems to me as though the programmer is forced to rely on global variables, which I find difficult to accept. Right now I have all the GLUT code in it's own module, running on it's own thread, and define a static pointer which I assign at the entry point to the module, like so:
Main module
int main( int argc, char** argv ) {
int foo;
boost::thread graphicsThread(glutMain, argc, argv, &foo);
//...
graphicsThread.join();
return 0;
}
GLUT module
static int* FOO_REF;
int glutMain( int argc, char** argv, int* foo ) {
FOO_REF = foo;
glutInit(&argc, argv);
//etc...
Is there a better solution than this?
If you're using freeglut or a derivative and willing to confine yourself to freeglut derivatives only it has a non-standard extension to solve exactly the problem. You can associate a void* with every window. If you make that a struct that contains all the per-window data you want you can avoid the globals entirely.
Synopsis:
#include <GL/glut.h>
#include <GL/freeglut_ext.h>
void * glutGetWindowData();
glutSetWindowData(void *data);
What I did was declare a global.h for all my globals. And initialize them in main. For my "basic/general" variables (ie camera, position, iterationNumber,...) they were all declared seperately. In main:
include "global.h"
Vector position_g = ...
Vector angles_g = ...
int time_g = 0;
int main () {
...
}
But for the variables that were "section specific" ie only in one game mode/level, I made a union and an enum.
enum mainGame{skipLevel, ...};
enum mainMenu {viewingSettings, ...};
typedef union generic_union {
int i;
char c;
bool b;
char s[100]; // or char * s;
float f;
} generic;
And declared a globalData variable.
extern generic * globalData; // in global.h
generic * globalData = NULL; // in main
Which can now be used:
int main () {
...
globalData = malloc (sizeof (generic)*numGlobals);
globalData[skipLevel].b = false;
...
}
Now when in your key press handling function, you can assign a key to toggle globalData[skipLevel]. And in any other file all you have to do is include global.h.
include "global.h"
void onKeyPress (... ) {
If (inMainGame) {
If (key == SPACE) {
globalData [skipLevel] = true;
}
}
And finally the use:
include "global.h"
void levelManager () {
...
if (globalData[skipLevel]) level++;
...
}
Pros
Only have to lug around 1 variable and one include.
You can free variables you no longer want or are using in that instance. (very useful for reducing "pollution"). If one game mode only needs 1 variable, thats all you have to store, if it needs 48, just as easy!
Can easily handle any variable type, by adding it to the union.
Totally Portable
Cons
Have to remember variable type to dereference the generic union (not that hard)
And watchout for enums being used (you can use a style for enums like mainMenu_e to solve this)
Adds complexity, but as the variable number grow, a system like this because well worth it.
Personally I find this very neat despite the few extra moving parts.
If this is unclear let me know, and Ill try to fix it :)