I have a lambda inside of a function that is capturing with [&] and then using a local static variable inside the lambda. I'm not sure if this valid to begin with, but this compiles and links fine:
void Foo()
{
static int i = 5;
auto bar = [&]()
{
i++;
};
bar();
}
int main()
{
Foo();
}
But by making Foo a templated function:
template <typename T>
void Foo()
{
static int i = 5;
auto bar = [&]()
{
i++;
};
bar();
}
int main()
{
Foo<int>();
}
I get the following error:
g++-4.7 -std=c++11 main.cpp
/tmp/cctjnzIT.o: In function 'void Foo()::{lambda()#1}::operator()() const':
main.cpp:(.text+0x1a): undefined reference to 'i'
main.cpp:(.text+0x23): undefined reference to 'i'
collect2: error: ld returned 1 exit status
So, I have two questions:
Is using i in the first example even valid c++?
If #1, then what is wrong with the second example? Or is this a gcc bug?
1) Yes, you can even drop & from definition because static is always accessible in lambda function.
2) It is bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54276
1) Yes, assuming you're intending to have 'i''s value persist between calls.
2) It's not a bug in the compiler. The static instance variable needs to also be defined via a template. Please refer to this post.
Related
Using Clang++ (v3.8.0), the following code fails to link due to sSomeValue being an undefined reference.
#include <iostream>
struct MyClass
{
static constexpr int sSomeSize = 3;
static constexpr int sSomeValue = 10;
};
int foo()
{
int someArray[MyClass::sSomeSize] = {};
std::fill(std::begin(someArray), std::end(someArray), MyClass::sSomeValue);
return someArray[0];
}
int main()
{
std::cout << foo() << std::endl;
}
More precisely:
clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
/tmp/main-c8de0c.o: In function `foo()':
main.cpp:(.text+0x2): undefined reference to `MyClass::sSomeValue'
/tmp/main-c8de0c.o: In function `main':
main.cpp:(.text+0x16): undefined reference to `MyClass::sSomeValue'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
However, changing the definition of foo to
int foo()
{
int someArray[MyClass::sSomeSize] = {MyClass::sSomeValue, MyClass::sSomeValue, MyClass::sSomeValue};
return someArray[0];
}
does not exhibit the same linker error, even though sSomeValue is still being used.
What is going on here? Is the compiler doing some optimization around the std::fill call that I may not be aware of?
Note that g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out compiles, links, and outputs 10 as expected with v6.3.0.
The error is nothing to do with std::fill.
If you refer below documentation, it says: Reference variables can be declared constexpr (their initializers have to be reference constant expressions):
http://en.cppreference.com/w/cpp/language/constexpr
Slight modification of your code works fine. Just make the struct variables "const &" as said above.
#include <iostream>
struct MyClass
{
static constexpr int const& sSomeSize = 3;
static constexpr int const& sSomeValue = 10;
};
int foo()
{
int someArray[MyClass::sSomeSize] = {};
std::fill(std::begin(someArray), std::end(someArray), MyClass::sSomeValue);
return someArray[0];
}
int main()
{
std::cout << foo() << std::endl;
}
Also refer here for well explained article about constexpr and static
"Does static constexpr variable make sense?
Specially the last para in ticked answer.
Why does the ASSERT_EQ below cause an undefined reference to Bar::kBar error?
To compile: g++ a.cc -lgtest -lpthread
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
From the Googletest FAQ:
The compiler complains about "undefined references" to some static const member
variables, but I did define them in the class body.
If your class has a static data member:
// foo.h
class Foo {
...
static const int kBar = 100;
};
You also need to define it outside of the class body in foo.cc:
const int Foo::kBar; // No initializer here.
Otherwise your code is invalid C++, and may break in unexpected ways.
In particular, using it in Google Test comparison assertions (EXPECT_EQ, etc)
will generate an "undefined reference" linker error.
This explanation is rather enigmatic. (Why is it "invalid C++?") That is
probably because a satisfactory explanation is rather technical.
Even though your class bar declares the static data member kBar with
an initializer, that does not suffice to provide the data member with a
definition that has external linkage (i.e. that the linker can see), and
without one any code that attempts to odr-use1 Bar::kBar will
encounter an undefined reference linkage error. This can be illustrated
without involving Googletest:
foobar.cpp
#include <cstdlib>
class Bar {
public:
static const std::size_t kBar = 0;
};
bool foo(std::size_t const & k)
{
return k == 0;
}
int main()
{
return foo(Bar::kBar);
}
Try to build:
$ g++ foobar.cpp
/tmp/ccWaEsDu.o: In function `main':
foobar.cpp:(.text+0x1c): undefined reference to `Bar::kBar'
collect2: error: ld returned 1 exit status
The solution is as per the FAQ:
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
const size_t Bar::kBar;
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
As of C++17 you will be able to omit the out-of-class definition if
you prefix the initialized in-class declaration with inline (which
will make it a definition).
[1] [ODR-use](http://en.cppreference.com/w/cpp/language/definition)
>Informally, an object is odr-used if its address is taken, or a reference is
>bound to it, and a function is odr-used if a function call to it is made or its
>address is taken. If an object or a function is odr-used, its definition must
>exist somewhere in the program; a violation of that is a link-time error.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
I have two files : a .cpp and a .hpp file. In the .hpp file there is a class with name Knoten and a public function definition :
static void faerbe_algorithmus(bool jsp[5][5], std::list< std::list<int> > &liste_von_str_orth_spalten);
In the .cpp file I am trying to call the function in another function (compute_J) like this :
Knoten::faerbe_algorithmus(jsp, liste_von_str_orth_spalten);
but I get the following error from g++ :
In function `compute_J(double*, double (*) [5])':
11_3.cpp:(.text+0x3fc): undefined reference to `Knoten::faerbe_algorithmus(bool (*) [5], std::list<std::list<int, std::allocator<int> >, std::allocator<std::list<int, std::allocator<int> > > >&)'
collect2: error: ld returned 1 exit status
What am I doing wrong? I can post more of the code, when needed.
Undefined reference often means that you have forgotten to add an implementation for the function you are trying to call.
For example:
Bad Foo.cpp
void doSomething();
int main()
{
doSomething(); // undefined reference, there is no implementation
}
Good Foo.cpp
void doSomething();
int main()
{
doSomething(); // this is OK, as the function is implemented later on
}
void doSomething()
{
// insert code here
}
If you have implemented the function somewhere, check the the name is qualified correctly.
For example (applies to both namespaces and classes/structs):
MyClass.hpp
class MyClass
{
public:
static void doSomething();
};
Bad MyClass.cpp
#include "MyClass.hpp"
void doSomething() // not qualified properly
{
// insert code here
}
Good MyClass.cpp
#include "MyClass.hpp"
void MyClass::doSomething() // now qualified properly
{
// insert code here
}
undefined reference to Knoten::faerbe_algorithmus
Is the sign that you are missing the definition for the static public function. You either forgot to define it with:
void Knoten::faerbe_algorithmus(bool jsp[5][5], std::list< std::list<int> > &liste_von_str_orth_spalten) {
// ...
}
or you are not linking the definition correctly.
On a side note, I'd suggest you to drop C-style arrays and start using std::array instead. It will save you a lot of troubles, especially with array to pointer decay. Here's the corresponding version:
void Knoten::faerbe_algorithmus(const std::array<std::array<bool, 5>, 5>& jsp, std::list< std::list<int> > &liste_von_str_orth_spalten) {
// ...
}
I know it's probably harder to write, but you can create an alias to it:
template<class Type, std::size_t Size>
using bidim = std::array<std::array<Type, Size>, Size>
and use it like:
void Knoten::faerbe_algorithmus(const bidim<bool, 5>& jsp, std::list< std::list<int> > &liste_von_str_orth_spalten) {
// ...
}
please consider these files:
p.h:
#ifndef _p_h_
#define _p_h_
class p{
public:
static void set_func(int(*)());
private:
static int (*sf)();
};
#endif
p.cpp:
#include "p.h"
#include <cstdio>
int (p::*sf)() = NULL; //defining the function pointer
void p::set_func(int(*f)()){
sf = f;
}
main.cpp:
#include "p.h"
#include <iostream>
int function_x(){
std::cout << "I'm function_x()" << std::endl;
return 1234;
}
int main(){
p::set_func(function_x);
}
when compiling, I get this:
$ g++ -o pp main.cpp p.cpp
/tmp/ccIs0M7r.o:p.cpp:(.text+0x7): undefined reference to `p::sf'
collect2: ld returned 1 exit status
but:
$ g++ -c -o pp p.cpp
compiles right.
What's wrong with the code? I just can't find where the problem is, please your help will be more than appreciated.
Thanks.
Your attempt at defining p::sf is incorrect – yours is a definition of a global variable named sf that is of type int (p::*)(), i.e. a pointer to a member function. Consequently p::sf remains undefined, hence the linker error.
Try this instead:
int (*p::sf)() = 0;
// or,
typedef int (*p_sf_t)();
p_sf_t p::sf = 0;
The difference is because error only occurs when you actually link the program. The problem is in your declaration of the static function pointer. The correct syntax is:
int (*p::sf)() = NULL; //defining the function pointer
You define a member function pointer and not a function pointer. I'm not sure what the correct syntax is, but I would have tried something like this:
int (*p::sf)() = NULL;
I will not give another answer (ildjarn answer is correct) but i will suggest you another way of achieving the same without static initialization (and the burdens it implies)
class p{
public:
typedef int (*func_t)();
static void set_func(func_t v) {
func_t& f = getFuncRef();
f = v;
}
static void call_func() {
func_t& f = getFuncRef();
assert( f != 0);
f();
}
private:
static func_t& getFuncRef() {
static func_t sf = 0;
return sf;
}
};
in this way you delegate the static initialization to a static function variable, which doesn't have the initialization order problems that affect static data variables, and is lazy-initialised
I have the following class definition and the main(). Can someone please point me why I am getting the error?
#include <iostream>
#include <list>
using namespace std;
class test
{
protected:
static list<int> a;
public:
test()
{
a.push_back(150);
}
static void send(int c)
{
if (c==1)
cout<<a.front()<<endl;
}
};
int main()
{
test c;
test::send(1);
return 0;
}
The error that I get is as follows:
/tmp/ccre4um4.o: In function `test::test()':
test_static.cpp:(.text._ZN4testC1Ev[test::test()]+0x1b): undefined reference to `test::a'
/tmp/ccre4um4.o: In function `test::send(int)':
test_static.cpp:(.text._ZN4test4sendEi[test::send(int)]+0x12): undefined reference to `test::a'
collect2: ld returned 1 exit status
The error is same even if I use c.send(1) instead of test::send(1). Thanks in advance for the help.
You've declared test::a, but you haven't defined it. Add the definition in namespace scope:
list<int> test::a;
a is declared but must still be defined.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12