undefined reference capturing static variable in lambda - c++

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

Clang static parameter to std::fill causing linker to fail

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.

Undefined reference with gtest

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.

Function call inside another function [duplicate]

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) {
// ...
}

Undefined reference to static function pointer member in c++, what am I doing wrong?

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

Static variables and functions usage

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