I do not understand why I cannot use a public const static member of a class in the initializer list of a map (probably any container). As I understand it "MyClass::A" is an rvalue, it seems like it should be the exact same as the case where I am using "THING" which is also a static const just outside of a class.
Here is the error:
Undefined symbols for architecture x86_64:
"MyClass::A", referenced from:
_main in map-380caf.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
And here is the code:
#include <iostream>
#include <map>
#include <string>
static const int THING = 1;
class MyClass {
public:
static const int A = 1;
};
int
main()
{
int a;
typedef std::map<int, std::string> MyMap;
// compiles and works fine
a = MyClass::A;
std::cout << a << std::endl;
// compiles and works fine
MyMap other_map = { {THING, "foo"} };
std::cout << other_map.size() << std::endl;
// Does not compile
MyMap my_map = { {MyClass::A, "foo"} };
std::cout << my_map.size() << std::endl;
return 0;
}
UPDATE 1:
Using clang on OS X:
Apple LLVM version 7.0.0 (clang-700.0.72)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
compiler flags:
clang++ map.cc -std=c++1y
Something in the map code probably tried to take the address of a reference to your int.
The class definition here:
class MyClass {
public:
static const int A = 1;
};
does not actually create any memory for A. In order to do that you have to do in the header file:
class MyClass {
public:
static const int A;
};
and in a CPP file:
const int MyClass::A = 1;
Or I guess with the newest C++ versions you can leave the = 1 in the header and just declare the storage in the CPP file with:
const int MyClass::A;
Related
I am trying to get some values from an array which is declared in another class. The array has a fixed length and constant elements (I will 100% never modify its values, so that's why I made it constant).
However, when I try to access the first element in the main function, I get a compilation error:
basavyr#Roberts-MacBook-Pro src % g++ -std=c++11 main.cc
Undefined symbols for architecture x86_64:
"Vectors::vec1", referenced from:
_main in main-c29f22.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1
As you can see, I'm compiling on macOS Catalina using clang (latest version).
[Q]:What could be the issue?
Thank you in advance.
Here is the code:
#include <iostream>
class Dimension
{
public:
static constexpr int dim1 = 2;
static constexpr int dim2 = 1;
};
class Vectors
{
public:
static constexpr double vec1[2] = {4.20, 6.9};
};
int main()
{
auto a = Vectors::vec1[0]; //I also tried initializing this to a value rather than just accessing it directly through the class like I did below
std::cout << a << "\n";
std::cout << Vectors::vec1[0] << "\n";
return 0;
}
You're compiling in C++11 mode; you need to provide definition for these constexpr static members at namespace scope. Note that this is not required since c++17.
If a const non-inline (since C++17) static data member or a constexpr static data member (since C++11) is odr-used, a definition at namespace scope is still required, but it cannot have an initializer. This definition is deprecated for constexpr data members (since C++17).
e.g.
class Dimension
{
public:
static constexpr int dim1 = 2;
static constexpr int dim2 = 1;
};
constexpr int Dimension::dim1;
constexpr int Dimension::dim2;
class Vectors
{
public:
static constexpr double vec1[2] = {4.20, 6.9};
};
constexpr double Vectors::vec1[2];
I do not understand why the below code compiles with GCC optimised, but fails to link with "undefined reference to `base::A_VAL'" when unoptimised. Am I doing something dodgy? Is this something that's a compiler bug (never is)? This is with g++ 5.4.0 on Ubuntu.
base.h:
class base {
public:
static constexpr unsigned int A_VAL{0x69U};
};
derived.h:
#include "base.h"
#include <iostream>
using namespace std;
class derived : public base
{
public:
int some_func(void) {
cout << "Some func" << endl;
return 0;
}
};
concrete.h:
#include "derived.h"
#include <utility>
class concrete : public derived
{
public:
concrete(int a, std::pair<unsigned int, unsigned int> data = {A_VAL, A_VAL}) {
some_func();
std::cout << "First: " << data.first << " Second: " << data.second << endl;
}
};
test.cpp:
#include "concrete.h"
int main (int argc, char *argv[])
{
concrete c{1};
c.some_func();
}
g++ -O2 -std=c++14 -o test test.cpp
Fine.
g++ -O0 -std=c++14 -o test test.cpp
/tmp/ccm9NjMC.o: In function `main':
test.cpp:(.text+0x23): undefined reference to `base::A_VAL'
test.cpp:(.text+0x28): undefined reference to `base::A_VAL'
collect2: error: ld returned 1 exit status
When optimizing GCC is probably able to determine (after inlining an constant folding) that the body of concrete's constructor can be replaced pretty much by
some_func();
std::cout << "First: " << A_VAL << " Second: " << A_VAL << endl;
Since operator<< for the standard stream class takes integers by value, and A_VAL is a constant expression, the call above doesn't require there to be any storage for A_VAL. Its value is just plugged in. As such, GCC doesn't need there to be an out of class definition for A_VAL, as is normally required for static class members.
When not optimizing, GCC quite likely initializes the pair object. std::pair's constructor takes objects by reference, and a reference requires an object to bind to. So the the definition of A_VAL becomes required and so the linker complains.
You need to define the object somewhere (pre C++17)
// At namespace scope
constexpr unsigned base::A_VAL;
Or switch to compiling as C++17. Then A_VAL (like all constexpr static members data) will be implicitly an inline variable, and the compiler will resolve its definition by itself.
I'm not sure howconstexpr affecting this, but you just declared static class variable, but not defined it. I.e. usually you need to have constexpr unsigned int base::A_VAL{0x69U}; somewhere in .cpp file.
This question already has answers here:
How to implement static class member functions in *.cpp file?
(7 answers)
What does "static" mean in C?
(20 answers)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 3 years ago.
I have class whose header file is defined as:
namespace mip {
class CustomStatic {
public:
static const char* GetVersion();
};
}
And class file is defined as:
#include "CustomStatic.h"
namespace mip {
static const char* GetVersion() {
return "hello";
}
}
I am accessing this static function from my main class
#include "CustomStatic.h"
#include <iostream>
using std::cout;
using mip::CustomStatic;
int main() {
const char *msg = mip::CustomStatic::GetVersion();
cout << "Version " << msg << "\n";
}
When I try to compile it using-
g++ -std=c++11 -I CustomStatic.h MainApp.cpp CustomStatic.cpp
I am getting error as:
Undefined symbols for architecture x86_64:
"mip::CustomStatic::GetVersion()", referenced from:
_main in MainApp-feb286.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code
1 (use -v to see invocation)
your static function is not properly implemented in the cpp file...
you need to do something like
//.h
namespace mip
{
class CustomStatic
{
public:
static const char* GetVersion();
};
}
//.cpp -> note that no static keyword is required...
namespace mip
{
const char* CustomStatic::GetVersion()
{
return "hello";
}
}
//use
int main(int argc, char *argv[])
{
const char* msg{mip::CustomStatic::GetVersion()};
cout << "Version " << msg << "\n";
}
My code is:
class cMySingleton{
private:
static bool bInstantiated;
int mInt;
cMySingleton(){
mInt=0;
}
public:
cMySingleton(int c){
if (bInstantiated){
cout << "you can only instantiated once";
}
else {
cMySingleton();
mInt=c;
}
}
};
int main () {
cMySingleton s(5);
cMySingleton t(6);
}
The linker keeps complaining:
Undefined symbols for architecture x86_64:
"cMySingleton::bInstantiated", referenced from:
cMySingleton::cMySingleton(int) in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
What is going on? C++ novice here~~
you should initialize static field.
http://ideone.com/Y1huV
#include <iostream>
class cMySingleton{
private:
static bool bInstantiated;
int mInt;
cMySingleton(){
mInt=0;
}
public:
cMySingleton(int c){
if (bInstantiated){
std::cout << "you can only instantiated once";
}
else {
cMySingleton();
mInt=c;
}
}
};
bool cMySingleton::bInstantiated = true;
int main () {
cMySingleton s(5);
cMySingleton t(6);
}
More information you can be find here:
Static Data Member Initialization
there was also missing include and std:: around cout.
Initialize
static bool bInstantiated;
outside of cMySingleton
bool CMySingleton::bInstantiated;
Dont forget to initialize your static member outside of your class declaration in .cpp file:
bool cMySingleton::bInstantiated = false;
The following code compiles fine. but when goes to linking,
it shows following error
Undefined symbols for architecture x86_64:
"derived::counter", referenced from:
derived::getAddressCounter() in main.cpp.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
I suspect there is something wrong with the static. but not sure why. Because once I take out the static, the code links fine. But how does static plays any role in this code?
#include <iostream>
#include <string>
struct base_result { };
struct result : public base_result {
int a;
std::string b;
};
struct base {
static base_result counter;
};
struct derived: public base {
static result counter;
result * getAddressCounter(){
counter.a = 10;
counter.b = "haha";
return &counter;
}
};
int main (){
derived d;
result * ptr;
ptr = d.getAddressCounter();
ptr->a = 20;
ptr->b = "baba";
std::cout << ptr->a << std::endl;
std::cout << ptr->b << std::endl;
return 0;
}
struct base
{
static base_result counter;
};
Only declares the static member, You also need to define it once in your cpp file.
Good Read:
What is the difference between a definition and a declaration?
In contrast to member variables which get a reserved space in every created object, static variables can't just be declared, they need to be implemented/defined too.
Just add the lines
base_result base::counter;
result derived::counter;
to your code and it will compile just fine. Those lines instructs the compiler to actually reserve space to store the static variables you declared earlier.