Static struct in C++ - c++

I want to define an structure, where some math constants would be stored.
Here what I've got now:
struct consts {
//salt density kg/m3
static const double gamma;
};
const double consts::gamma = 2350;
It works fine, but there would be more than 10 floating point constants, so I doesn't want to wrote 'static const' before each of them. And define something like that:
static const struct consts {
//salt density kg/m3
double gamma;
};
const double consts::gamma = 2350;
It look fine, but I got these errors:
1. member function redeclaration not allowed
2. a nonstatic data member may not be defined outside its class
I wondering if there any C++ way to do it?

Use a namespace rather than trying to make a struct into a namespace.
namespace consts{
const double gamma = 2350;
}
The method of accessing the data also has exactly the same synatx. So for example:
double delta = 3 * consts::gamma;

It sounds like you really just want a namespace:
namespace consts {
const double gamma = 2350.0;
// ...
}
Except I'd try to come up with a better name than consts for it.

Related

How do I assign to a const variable using an out parameter in C++?

In a class header file Texture.h I declare a static const int.
static const int MAX_TEXTURE_SLOTS;
In Texture.cpp I define the variable as 0.
const int Texture::MAX_TEXTURE_SLOTS = 0;
Now in Window.cpp class's constructor I attempt to assign to the variable using an out parameter, however this obviously does not compile as &Texture::MAX_TEXTURE_SLOTS points to a const int* and not an int* .
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &Texture::MAX_TEXTURE_SLOTS);
I have tried using const_cast, but am greeted with a segmentation fault on runtime.
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, const_cast<int*>(&Texture::MAX_TEXTURE_SLOTS));
I have also tried directly casting to an int * but once again, seg fault.
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (int*)&Texture::MAX_TEXTURE_SLOTS);
Many thanks.
EDIT 2: So since you're trying to abstract OpenGL contexts, you'll have to let go of the "traditional" constructor/destructor idioms. And just for your information (unrelated to this question): OpenGL contexts are not tied to windows! As long as a set of windows and OpenGL contexts are compatible with each other, you may mix and match any way you like. But I digress.
The standard idiom to deal with a situation like yours is to use preinitializing factory functions. Like this:
class MyOpenGLContextWrapper {
public:
// Yes, shared_ptr; using a unique_ptr here for objects that are kind
// of a nexus for other things -- like an OpenGL context -- just creates
// a lot of pain and misery. Trust me, I know what I'm talkink about.
typedef std::shared_ptr<MyOpenGLContextWrapper> ptr;
struct constdata {
NativeGLContextType context;
// ...
GLint max_texture_image_units;
// ...
};
static ptr create();
protected:
MyOpenGLContextWrapper(constdata const &cdata) : c(cdata) {};
virtual ~MyOpenGLContextWrapper();
constdata const c;
}
MyOpenGLContextWrapper::ptr MyOpenGLContextWrapper::create()
{
struct object : public MyOpenGLContextWrapper {
object(MyOpenGLContextWrapper::constdata const &cdata) : MyOpenGLContextWrapper(cdata) {}
~object(){}
};
MyOpenGLContextWrapper::constdata cdata = {};
// of course this should all also do error checking and failure rollbacks
cdata.context = create_opengl_context();
bind_opengl_context(cdata.context);
// ...
glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS, &cdata.max_texture_image_units);
return std::make_shared<object>(cdata);
}
EDIT: I just saw that you intend to use this to hold on to a OpenGL limit. In that case you can't do this on a global scope anyway, since those values depend on the OpenGL context in use. A process may have several OpenGL contexts, each with different limits.
On most computer systems you'll encounter these days, variables declared const in global scope will be placed in memory that has been marked as read only. You literally can't assign to such a variable.
The usual approach to implement global scope runtime constants is by means of query functions that will return from an internal or otherwise concealed or protected value. Like
// header.h
int runtime_constant();
#define RUNTIME_CONSTANT runtime_constant()
// implementation.c / .cpp
int runtime_constant_query(){
static int x = 0;
// NOTE: This is not thread safe!
if( !x ){ x = determine_value(); }
return x;
}
You can then fetch the value by calling that function.
Provided that glGetIntegerv doesn't depend on other gl* functions being called before, you may use an immediately-invoked lambda:
// Texture.cpp
const int Texture::MAX_TEXTURE_SLOTS = []
{
int maxTextureSlots{0}:
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureSlots);
return maxTextureSlots;
}();
You don't.
You can't assign to a const outside of its definition. Also, using a const variable where the const has been const_casted away is UB. This also means you can't directly initialize a const variable with an output parameter. For trivial types, just output to another variable and make a const copy if you so wish.
If you were the author of the function you're calling, you would do well not to use out parameters, and then you could assign to const variables directly, perhaps using structured bindings if you want to name multiple of the outputs at a time. But here, you're not.

Static const variable definitions being ignored and instead initialized to 0

I have a long list of static consts that I need to use inside of a class. So rather than clutter up the class definition, I put them into a struct and defined my class to inherit the member variables of that struct like so:
/*The following code is all in the same header file in the order shown*/
struct constants{
static const double a1, a2, a3, .... ;
};
const double constants::a1 = 142314321.6536;
const double constants::a2 = 652453254.1343;
const double constants::a3 = 652134324.1234;
...(etc).
class C : constants {
//class definition...
void myFunction();
};
void C::myFunction() {
double a = a1*a2 ...;
...
}
My code compiles with no errors and runs without any errors. However, I was getting nonsense results and found that when I ran my code in the debugger, all of my static const values were zero.
What is happening that is initializing these variables to 0 but also not throwing an error at the way the variables are defined?
EDIT: I should mention, my method of preventing multiple header declarations is to use #pragma once at the top of every header file.

Create a function from another one

more than a general case, I have a very specific example in mind : in GSL (GNU Scientific Library), the main function type used (in order to perform integration, root finding,...) is gsl_function , which have an attribute function whose type is double(*)(double, void *)
Say I want to create a gsl_function from double a_squared(double a) {return a*a};. a__squared 's type is double(*)(double) I would like to create a convert function taking in argument (double(*)(double) f) and returning an object of type double(*)(double, void *) which would satisfy convert(f)(double a, NULL) == f(a)
But after some research, it seems like I can't define another function in my convert function. How to proceed ?
The need to pass a raw function pointer to the GSL API limits your options considerably - you can't use anything based on std::function because there's no way to obtain a function pointer from a std::function (and this rules out lambdas using captures, which would have offered a neat solution).
Given these constraints, here's a possible solution making use of a static wrapper class. You could just as well have put the contents of this class in a namespace, but using the class at least gives some semblance of encapsulation.
typedef double gsl_function_type(double, void*); // typedef to make things a bit more readable...
// static class to wrap single-parameter function in GSL-compatible interface
// this really just serves as a namespace - there are no non-static members,
// but using a class lets us keep the details private
class Convert
{
Convert() = delete; // don't allow construction of this class
// pointer to the function to be invoked
static double (*m_target)(double);
// this is the function we'll actually pass to GSL - it has the required signature
static double target(double x, void*) {
return m_target(x); // invoke the currently wrapped function
}
public:
// here's your "convert" function
static gsl_function_type* convert(double (*fn)(double)) {
m_target = fn;
return &target;
}
};
There's a live example here: http://coliru.stacked-crooked.com/a/8accb5db47a0c51d
You're trapped by gsl's (poor) design choice of using C (instead of C++) to provide a C-style function pointer. Thus, you cannot use (C++ style) function-objects (functor), but must provide the pointer to a real function and one cannot generate a function in the same way one can genarate functors.
(Not recommended) You can use a global variable to store the actual function (a_squared) and then define a particular gsl_function that actually calls that global variable:
// from some gsl header:
extern "C" {
typedef double gsl_function(double, void*);
// calls func(arg,data_passed_to_func)
double gsl_api_function(gsl_function*func, void*data_passed_to_func);
}
// in your source code
double(*target_func)(double); // global variable can be hidden in some namespace
extern "C" {
double funtion_calling_target(double, void*)
}
double funtion_calling_target(double arg, void*)
{
return target_func(arg);
}
bool test(double x, double(*func)(double))
{
target_func = func;
return x < gsl_api_function(function_calling_target,0);
}
(hiding target_func as static member of some class as in atkins's answer still requires a global variable). This works, but is poor, since 1) this mechanism requires a global variable and 2) only allows one target function to be used a any time (which may be hard to ensure).
(Recommended) However, you can define a special function that takes another function pointer as argument and passes it as data element. This was in fact the idea behind the design of gsl_function: the void* can point to any auxiliary data that may be required by the function. Such data can be another function.
// your header
extern "C" {
double function_of_double(double, void*);
}
inline double function_of_double(double arg, void*func)
{
typedef double(*func_of_double)(double);
return reinterpret_cast<func_of_double>(func)(arg);
}
// your application
bool test(double x, double(*func)(double))
{
return x < gsl_api_function(function_of_double, (void*)(func));
}
This does not require a global variable and works with as many different simultaneous functions as you want. Of course, here you are messing around with void*, the very thing that every sensible C++ programmer abhors, but then you're using a horrible C library which is based on void* manipulations.
Thought I would add my lambda-based attempts at this.
It works fine in principle:
// function we want to pass to GSL
double a_squared(double a) { return a*a; }
typedef double gsl_function_type(double, void*); // convenient typedef
// lambda wrapping a_squared in the required interface: we can pass f directly to GSL
gsl_function_type* f = [](double x, void*) { return a_squared(x); };
But we'd really like to write a method to apply this to any given function. Something like this:
gsl_function_type* convert(double (*fn)(double))
{
// The lambda has to capture the function pointer, fn.
return [fn](double x, void*) { return fn(x); };
}
However, the lambda now has to capture the pointer fn, because fn has automatic storage duration (in contrast to the static function a_squared in the first example). This doesn't compile because a lambda which uses a capture cannot be converted to a simple function pointer, as required by the return value of our function. In order to be able to return this lambda we'd have to use a std::function, but there's no way to get a raw function pointer from that, so it's no use here.
So the only way I've managed to get this to work is by using a preprocessor macro:
#define convert(f) [](double x, void*) { return f(x); }
This then lets me write something like this:
#include <iostream>
using namespace std;
typedef double gsl_function_type(double, void*); // convenient typedef
// example GSL function call
double some_gsl_function(gsl_function_type* function)
{
return function(5.0, nullptr);
}
// function we want to pass to GSL
double a_squared(double a) { return a*a; }
// macro to define an inline lambda wrapping f(double) in GSL signature
#define convert(f) [](double x, void*) { return f(x); }
int main()
{
cout << some_gsl_function(convert(a_squared)) << endl;
}
Personally, as much as I dislike using macros, I would prefer this over my other suggestion. In particular, it solves the problems #Walter pointed out with that idea.
Previous answers - including the accepted one - seem correct, but they are not general enough in case you need to convert other types of function to gsl_function (including member functions for example). So, let me add a more powerful alternative.
If you use the wrapper described here, then you can convert any C++ lambdas to gsl_functions in two simple lines
// Example
gsl_function_pp Fp([&](double x){return a_squared(x);});
gsl_function *F = static_cast<gsl_function*>(&Fp);
This solves any related conversion problems. You can also use std::bind and any std::functions.

const array declaration in C++ header file

I have a class called AppSettings where I have an Array with a range of note frequencies. I'm getting several errors with the code below and I'm not sure what the problem is.
The error messages are:
static data member of type 'const float [36] must be initialized out of line
A brace enclosed initializer is not allowed here before '{' token
Invalid in-class initialization of static data member of non-integral type
And the code:
class AppSettings{
public:
static const float noteFrequency[36] = {
// C C# D D# E F F# G G# A A# B
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
};
};
As the name suggests this is just a header file with some settings and values I need throughout the app.
You can't define the value of static class members within the class. You need to have a line like this in the class:
class AppSettings
{
public:
static const float noteFrequency[];
And then in an implementation file for the class (AppSettings.cpp perhaps):
const float AppSettings::noteFrequency[] = { /* ... */ };
Also, you don't need to specify the number within the [] here, because C++ is smart enough to count the number of elements in your initialization value.
This works just fine in C++11
class AppSettings{
public:
static constexpr float noteFrequency[36] = {
// C C# D D# E F F# G G# A A# B
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
};
};
C++03 doesn't support in-class definitions of complex data like arrays of constants.
To place such a definition at namespace scope in a header file, and avoid breaking the One Definition Rule, you can leverage a special exemption for template classes, as follows:
#include <iostream>
using namespace std;
//----------------------------------------- BEGIN header file region
template< class Dummy >
struct Frequencies_
{
static const double noteFrequency[36];
};
template< class Dummy >
double const Frequencies_<Dummy>::noteFrequency[36] =
{
// C C# D D# E F F# G G# A A# B
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
};
class AppSettings
: public Frequencies_<void>
{
public:
};
//----------------------------------------- END header file region
int main()
{
double const a = AppSettings::noteFrequency[21];
wcout << a << endl;
}
There are also some other techniques that can be used:
An inline function producing a reference to the array (or used as indexer).
Placing the definition in a separately compiled file.
Simply computing the numbers as needed.
Without more information I wouldn’t want to make the choice for you, but it shouldn’t be a difficult choice.

How can I initialize class variables in a header?

I'm writing a library where the user can define arbitrary structures and pass them to my library, which will then obtain the memory layout of the structure from a static member such structure must have as a convention.
For example:
struct CubeVertex {
// This is, per convention, required in each structure to describe itself
static const VertexElement Elements[];
float x, y, z;
float u, v;
};
const VertexElement CubeVertex::Elements[] = {
VertexElement("Position", VertexElementType::Float3),
VertexElement("TextureCoordinates", VertexElementType::Float2),
};
C++ best practices would suggest that I move the static variable and its initialization into my source (.cpp) file. I, however, want to keep the variable initialization as close to the structure as possible since whenever the structure changes, the variable has to be updated as well.
Is there a portable (= MSVC + GCC at least) way to declare such a variable inside the header file without causing ambiguous symbol / redefinition errors from the linker?
Consider a simple getter.
struct CubeVertex {
static const std::array<VertexElement, N>& GetElements() {
static const std::array<VertexElement, N> result = {
//..
};
return result;
}
//..
}
Immediate benefit: No array-to-pointer-decay.
What you could do here is using an anonymous namespace.
Wrap everything into "namespace { ... };" and you can then access CubeVertex::Elements like you normally do.
However, this creates a new instance of the static data everytime you include the headerfile, which adds to the executable's filesize.
It also has some limitations on how to use the class/struct, because you cannot call functions of that class from another file (which won't be a problem in this special case here).