const array declaration in C++ header file - c++

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.

Related

Is there a way to avoid constexpr function used in header file from entering global scope without extra namespace for it?

I have a header file with code simply looking like this:
constexpr uint32 GenTag(const char tag[5]) { ... }
class SomeClass
{
static constexpr uint32 TAG1 = GenTag("smth");
static constexpr uint32 TAG2 = GenTag("abcd");
};
//constexpr needed for switch-case statement
The problem is that function GenTag() belongs to global scope and I would like to avoid it if possible.
I wanted to declare it inside class but it is not possible with constexpr (explanation here: constexpr not working if the function is declared inside class scope).
Does c++ have anything like "undeclare" function at the end of the header (maybe some macro tricks)? Or any other options I missed? If no better ways exist I would probably go with extra (maybe excessive) namespace, but want to ask if there are any other ideas.
There's no way to "undeclare" a function or variable in C++ (header file or not -- a header file is just included into the current translation unit). You'll need to use a namespace, or make GenTag into a macro. You can undefine macros with #undef MACRONAME.
What about defining GenTag() as a static constexpr method in an inherited struct?
If you want that GenTag() is usable only inside SomeClass, you can make it private and define SomeClass as friend inside the class containing GenTag().
I mean... something as follows
#include <iostream>
struct SomeClass;
class foo
{
static constexpr char GenTag(const char tag[5])
{ return tag[0]; }
friend SomeClass;
};
struct SomeClass : public foo
{
static constexpr char TAG1 = GenTag("smth");
static constexpr char TAG2 = GenTag("abcd");
};
int main()
{
std::cout << "Tag1: " << SomeClass::TAG1 << std::endl;
std::cout << "Tag2: " << SomeClass::TAG2 << std::endl;
// compilation error: 'GenTag' is a private member of 'foo'
// static constexpr char TAG3 = foo::GenTag("wxyz");
}
With the friend trick, you don't need to inherit from foo; but, without inheritance, you have to use it as foo::GetTag().
If anyone ever will also meet a problem like this I would recommend you to not use such constexpr in header at all but consider to declare-define it directly in and only in cpp file instead. Then you will definitely avoid unnecessary global scope pollution.
Or if there are multiple places where such constants can be used then make a separate heared for them without any classes and include that file separately from including class definition header.

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.

C++ : nameable objects belonging to an instance of a class, and stored in it

I am trying to make it possible for a programmer (who uses my library) to create nameable instances of type X that are stored inside an instance of class C (or at least are exclusive to that instance).
These are the only two (ugly) solutions I have managed to come up with (needless to say, I am just picking up C++)
1)
class C
{
public:
class XofC
{
public:
XofC() = delete;
XofC(C& mom)
{
mom.Xlist.emplace_front();
ref = Xlist.front();
}
X& access()
{
return ref;
}
private:
X& ref;
};
//etc
private:
std::forward_list<X> Xlist;
friend class XofC;
//etc
}
Problem:
Having to pass everywhere XofC instances.
2)
class C
{
public:
void newX(std::string);
X& getX(std::string);
//etc.
private:
/*possible run-time mapping implementation
std::vector<X> Xvec;
std::unordered_map<std::string, decltype(Xvec.size())> NameMap;
*/
//etc
}
Problem:
This does the job, but since all names of X (std::string) are known at compilation, the overhead of using run-time std::unordered_map<std::string, decltype(Xvec.size())> kind-of bugs me for something this simple.
Possible(?) solution: compile-time replacing of std::string with automatic index (int). Then I could use:
class C
{
public:
void newX(int); //int: unique index calculated at compile time from std::string
X& getX(int); //int: unique index calculated at compile time from std::string
//etc.
private:
std::vector<X> Xvec;
}
Questions:
Is there a 3)?
Is a compile time solution possible for 2)?
This is the real-life situation: I was starting my first C++ "project" and I thought I could use the practice and utility from an awesome user-friendly, simple and fast argument management library. I plan to make an ArgMan class which can parse the argV based on some specified switches. Switches would be named by the programmer descriptively and the trigger strings be specified (e.g. a switch named recurse could have "-r" and "-recursive" as triggers). When necessary, you should be easily able to get the setting of the switch. Implementation detail: ArgMan would have a std::unordered_map<std::string/*a trigger*/, ??/*something linking to the switch to set on*/>. This ensures an almost linear parse of argV relative to argC. How should I approach this?
You could 'abuse' non-type template arguments to get compiletime named instances:
Live on Coliru
Assume we have a data class X:
#include <string>
struct X
{
int has_some_properties;
std::string data;
};
Now, for our named instances, we define some name constants. The trick is, to give them external linkage, so we can use the address as a non-type template argument.
// define some character arrays **with external linkage**
namespace Names
{
extern const char Vanilla[] = "Vanilla";
extern const char Banana [] = "Banana";
extern const char Coconut[] = "Coconut";
extern const char Shoarma[] = "Shoarma";
}
Now, we make a NamedX wrapper that takes a const char* non-type template argument. The wrapper holds a static instance of X (the value).
// now we can "adorn" a `namedX` with the name constants (above)
template <const char* Name>
struct NamedX
{
static X value;
};
template <const char* Name> X NamedX<Name>::value;
Now you can use it like this:
int main()
{
X& vanilla = NamedX<Names::Vanilla>::value;
vanilla = { 42, "Woot!" };
return vanilla.has_some_properties;
}
Note that due to the fact that the template arguments are addresses, no actual string comparison is done. You cannot, e.g. use
X& vanilla = NamedX<"Vanilla">::value;
becuase "Vanilla" is a prvalue without external linkage. So, in fact you could do without some of the complexity and use tag structs instead: Live on Coliru
While Neil's solution did what I asked for, it was too gimmicky to use in my library. Also, sehe's trick is surely useful, but, if I understood correctly, but doesn't seem related to my question. I have decided to emulate the desired behavior using method 1), here is a less broken attempt at it:
class C
{
private:
class X
{
//std::string member;
//etc
};
public:
class XofC
{
public:
XofC(C & _mom) : mom(_mom)
{
mom.Xlist.emplace_front();
tehX = &(Xlist.front());
}
X & get(maybe)
{
if (&maybe != &mom) throw std::/*etc*/;
return &tehX;
}
private:
X * tehX;
C & mom;
};
private:
//etc
std::forward_list<X> Xlist;
friend class XofC;
//etc
};
Usage:
C foo;
bar = C::XofC(foo); //acts like an instance of X, but stored in C, but you have to use:
bar.get(foo)/*reference to the actual X*/.member = "_1_";
Of course, the downside is you have to make sure you pass bar everywhere you need it, but works decently.
This is how it looks like in my tiny argument manager library:
https://raw.github.com/vuplea/arg_manager.h/master/arg_manager.h

fill vector with data inside a class fnc

I have a custom data type array and vector as below. In Foo function i started to fill array and vector with data. Anyway there was no problem filling array with data. However i couldn't access anything with vector. I could not find what i am missing .
Is there a way to fill the vector objects with data.
// MyClass.h
#include <cliext/vector>
using namespace System;
using namespace cliext;
public ref class MyClass {
private :
static int x ;
static float y ;
String ^name;
public :
static array<MyClass ^> ^myArray = gcnew array <MyClass^> (3) ;
static vector<MyClass^> ^myVector = gcnew vector <MyClass^> (3) ;
void Foo();
};
// MyClass.cpp
#include "stdafx.h"
#include <MyClass.h>
void MyClass::Foo()
{
myArray[0] = gcnew MyClass;
myVector[0] = gcnew MyClass;
myArray[0]->x = 100 ;
myArray[0]->x = 99.5 ;
myArray[0]->name = "Good" ;
myVector[0]->CAN'T ACCESS ANY CLASS DATA MEMBER !!
}
Here's the MSDN explaining what's happening: How to: Expose an STL/CLR Container from an Assembly
"STL/CLR containers such as list and map are implemented as template ref classes. Because C++ templates are instantiated at compile time, two template classes that have exactly the same signature but are in different assemblies are actually different types. This means that template classes cannot be used across assembly boundaries."
As I understand it, your public class is attempting to export a template specialization of vector but this will have a different signature from an external declaration of the same vector and would never match.
You may want to change the myVector element like this (which compiles for me):
static cliext::vector<MyClass^>::generic_container ^myVector = gcnew cliext::vector<MyClass^>(3);
Another option is to not mark your class as 'public' so the compiler doesn't attempt to make it usable outside of your assembly.
I'll also note that using 'static' on x and y seems suspect to me. You sure you only want one of those?

Syntax error when initializing a static variable

There are two classes defined..
class Dictionary
{
public:
Dictionary();
Dictionary(int i);
// ...
};
and
class Equation
{
static Dictionary operator_list(1);
// ...
};
but the problem is, whenever I compile this, I get a weird error message
error C2059: syntax error : 'constant'
But it compiles well when I use the default constructor on operator_list.
In C++ you cannot combine declaration and initialization. When you do not specify constructor parameters of operator_list, you do not call its default constructor: you simply declare it. You need to also initialize it in the corresponding C++ file, like this:
Equation.h
class Equation {
static Dictionary operator_list;
};
Equation.cpp:
Dictionary Equation::operator_list(1);
Note the absence of static in the CPP file: it is not there by design. The compiler already knows from the declaration that operator_list is static.
Edit: You have a choice with static constant members of integral and enumerated types: you can initialize them in the CPP file as in the example above, or you can give them a value in the header. You still need to define that member in your C++ file, but you must not give it a value at the definition time.
static Dictionary operator_list(); is a function signature declaring a function returning a Dictionary and taking no arguments, that's why your compiler let you do it.
The reasons static Dictionary operator_list(1); fails is because you can't set a value of an complex type in the declaration of your classes. You need to do this elsewhere (e.g. in the .cpp )
For more information, see this post : https://stackoverflow.com/a/3792427/103916
#include <iostream>
using namespace std;
class Dictionary
{
public:
Dictionary() {}
Dictionary(int i):page(i) {}
void display() { cout << "page is " << page << endl; }
private:
int page;
};
class Equation
{
public:
static Dictionary operator_list;
};
Dictionary Equation::operator_list(1); // static members must be initialized this way...
int main()
{
Equation::operator_list.display();
}
Output is:
page is 1