STL, GCC and explicit template instantiation - c++

Question: Why does the code below not work?
I want to use explicit template instantiation for my project. However, when I try to instantiate a standard algorithm (std::find) it seems like I also need to instantiate some internal routine. It says:
undifined reference to Foo* std::__find<Foo const*, unsigned int>(Foo const*,
Foo const*, unsigned int const&, std::random_access_iterator_tag)
when I
template
Foo* std::find<Foo*,unsigned int>(Foo*,Foo*,const unsigned int&);
More precicly, I am trying to do the following:
#include <algorithm>
#include <cstdio>
class Foo
{
public:
unsigned int id;
bool operator==(unsigned int b)
{return id==b;}
};
template
Foo* std::find<Foo*,unsigned int>(Foo*,Foo*,const unsigned int&);
int main()
{
Foo bar[4]={1,2,3,4};
Foo* p_bar=std::find(bar,bar+4,3);
printf("%p %u\n",p_bar,*p_bar);
return 0;
}
And it compile using
g++ -fno-explicit-templates test.cpp
to force explicit template instantiation.
The compiler output is as follows:
ccWFduTJ.o:test.cpp:(.text$_ZSt4findIP3FoojET_S2_S2_RKT0_[Foo* std::find<Foo*, unsigned int>(Foo*, Foo*, unsigned int const&)]+0x2a): undefined reference to `Foo* std::__find<Foo*, unsigned int>(Foo*, Foo*, unsigned int const&, std::random_access_iterator_tag)'
ccWFduTJ.o:test.cpp:(.text$_ZSt4findIP3FooiET_S2_S2_RKT0_[Foo* std::find<Foo*, int>(Foo*, Foo*, int const&)]+0x2a): undefined reference to `Foo* std::__find<Foo*, int>(Foo*, Foo*, int const&, std::random_access_iterator_tag)'
collect2: ld returned 1 exit status
If it helps, here is what g++ --version outputs:
g++ (tdm-1) 4.5.2
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Just as a quick test, this builds for me:
#include <algorithm>
using namespace std;
class Foo
{
};
template<>
Foo* std::find<Foo*, unsigned int>(Foo*, Foo*, const unsigned int& )
{
return NULL;
}
int main( int argc, char *argv )
{
return 0;
}

Related

undefined reference to c++ static library from c code when compiling using g++

I want to try interfacing C++ from C using the following setup:
interface.h:
#ifndef MY_TEST_INTERFACE_H
#define MY_TEST_INTERFACE_H
void *CreateDictionary();
void DictionaryAdd(void *self, const char *key, const char *value);
const char *DictionaryGetItem(void *self, const char *key);
void ReleaseDictionary(void **self);
#endif /* MY_TEST_INTERFACE_H */
lib.cpp
#include <unordered_map>
extern "C" void *CreateDictionary()
{
std::unordered_map<const char *, const char *> *dict = new std::unordered_map<const char *, const char *>;
return reinterpret_cast<void *>(dict);
}
extern "C" void DictionaryAdd(void *self, const char *key, const char *value)
{
std::unordered_map<const char *, const char *> *dict = reinterpret_cast<std::unordered_map<const char *, const char *> *>(self);
(*dict)[key] = value;
}
extern "C" const char *DictionaryGetItem(void *self, const char *key)
{
std::unordered_map<const char *, const char *> *dict = reinterpret_cast<std::unordered_map<const char *, const char *> *>(self);
return (*dict)[key];
}
extern "C" void ReleaseDictionary(void **self)
{
std::unordered_map<const char *, const char *> **dict = reinterpret_cast<std::unordered_map<const char *, const char *> **>(self);
delete (*dict);
*self = 0;
}
main.c
#include "interface.h"
#include <stdio.h>
int main(int argc, char **argv)
{
void *dict = CreateDictionary();
DictionaryAdd(dict, "color", "Green");
const char *str = DictionaryGetItem(dict, (const char *)"color");
puts(str);
ReleaseDictionary(&dict);
return 0;
}
What I did
I compiled lib.cpp using
g++ lib.cpp -o lib.obj -std=c++11 -std=gnu++11-c
Then built the static libary using
ar crf lib.a lib.obj
I am now trying to link lib.a with main.c using
g++ main.c lib.a -o main -std=c++11 -std=gnu++11
However I am getting the error:
C:\Users\Dmitry\AppData\Local\Temp\ccWnD011.o:main.c:(.text+0xf): undefined reference to `CreateDictionary()'
C:\Users\Dmitry\AppData\Local\Temp\ccWnD011.o:main.c:(.text+0x2f): undefined reference to `DictionaryAdd(void*, char const*, char const*)'
C:\Users\Dmitry\AppData\Local\Temp\ccWnD011.o:main.c:(.text+0x43): undefined reference to `DictionaryGetItem(void*, char const*)'
C:\Users\Dmitry\AppData\Local\Temp\ccWnD011.o:main.c:(.text+0x5f): undefined reference to `ReleaseDictionary(void**)'
collect2.exe: error: ld returned 1 exit status
I am building this on MINGW g++ 5.3.0.
I am curious why my C program can't find the references to the functions I marked under extern C, and compiled using g++ to ensure the c++ runtime is linked.

c++ undefined reference to member function defined outside of header file

I am under the impression that you are allowed to define member functions of a class in one file and then use those functions in another file, as long as both files are compiled and sent to the linker. However, doing this gives me an undefined reference error if I use g++ (4.6.4). Interestingly, using the intel compiler (icpc 11.0) does not give an error and everything works. Is there some flag I can set in g++ to make this work, or is the intel compiler letting me get away with something I shouldn't be doing? Here is some code that reproduces my problem:
class.h:
#ifndef _H
#define _H
typedef class
{
public:
int a;
int b;
void set(int x, int y);
int add(void);
} Test;
#endif
class.cpp:
#include "class.h"
void Test::set(int x, int y)
{
a = x;
b = y;
}
int Test::add(void)
{
return a+b;
}
main.cpp:
#include <cstdio>
#include "class.h"
int main(void)
{
Test n;
n.set(3, 4);
printf("%d\n", n.add());
return 0;
}
To compile, I do:
$ g++ class.cpp main.cpp -o test
/tmp/ccRxOI40.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `Test::set(int, int)'
main.cpp:(.text+0x26): undefined reference to `Test::add()'
collect2: ld returned 1 exit status
Okay, this is strange, but what happened is that this construct:
typedef class
{
public:
int a;
int b;
void set(int x, int y);
int add(void);
} Test;
while legal is not being treated semantically the same by the compiler as:
class Test
{
public:
int a;
int b;
void set(int x, int y);
int add(void);
};
The typedef version makes your methods static to the file, as indicated in the nm output:
$ nm class.o
0000000000000024 t _ZN4Test3addEv
0000000000000000 t _ZN4Test3setEii
U __gxx_personality_v0
While the class Test version makes them proper methods:
$ nm class2.o
0000000000000024 T _ZN4Test3addEv
0000000000000000 T _ZN4Test3setEii
U __gxx_personality_v0
This is why the linker failed to find the symbols.
Edit: As to why this is happening, it seems to be due to an issue with interpreting how the Standard specifies the treatment of the typedef name as a class-name. Newer compilers do not seem to exhibit the same issue. The problem reported in this question was reproduced with g++ 4.4.7.
If you move the code in your class.cpp file into main.cpp and only compile main.cpp, things will work. Alternatively, you can inline the method definitions into class.h.
If you want to leave them as separate translation units, you need to change the class.h file so that your class is defined using the class Test way instead of using the typedef on the anonymous class.

GTEST - ASSERT_EQ and EXPECT_EQ compile error

I have been trying to use the assertion of ASSERT_EQ and EXPECT_EQ,
ASSERT_EQ(queue_->size(),6);
even using this
ASSERT_EQ(6,6);
However, I encountered this compiler error and everywhere I searched no one seems to be facing
this problem.
/tmp/cczZfMaq.o: In function testing::AssertionResult testing::internal::EqHelper<false>::Compare<char, char>(char const*, char const*, char const&, char const&)':
/usr/include/gtest/gtest.h:1485: undefined reference totesting::AssertionResult testing::internal::CmpHelperEQ(char const*, char const*, char const&, char const&)'
collect2: error: ld returned 1 exit status
make: * [priority_queue_test.out] Error 1
Full Test File :
//Include the class which you would like to test
#include "priority_queue.h"
//Include the google c++ test framework
#include
#include
#include
//use the namespace for the testing class
using namespace algorithms;
using namespace containers;
namespace{
//Test Fixture Class
//multple tests in a test case shared common objects and subroutines
class PriorityQueueTest : public ::testing::Test{
protected:
PriorityQueueTest(){
}
virtual ~PriorityQueueTest(){
}
virtual void SetUp(){
queue_ = new PriorityQueue(1000);
}
virtual void TearDown(){
}
PriorityQueue *queue_=NULL;
};
TEST_F(PriorityQueueTest,CheckAllMemberInitSuccessfully){
//ASSERT is a critcal assertion which will fail the test program
ASSERT_TRUE(queue_!=NULL) capacity()==1000) capacity();
}
TEST_F(PriorityQueueTest,CheckIfItemsAreEnqueueCorrectly){
//test cases
queue_->Enqueue(0,0);
queue_->Enqueue(1,1);
queue_->Enqueue(6,6);
queue_->Enqueue(5,5);
queue_->Enqueue(3,3);
queue_->Enqueue(2,2);
ASSERT_EQ('a','a');
}
}//namespace
int main(int argc, char *argv[]){
::testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}

C++: Undefined reference to function in namespace

Here I am, trying to figure out what's wrong with my code without success :(
I'm writing a resampler but I guess that's of no interest at all, I'm just trying yo make this stupid warning go away. Anyway, here's my code:
ddc.hpp
#ifndef __DIGITAL_DOWN_CONVERTER_H__
#define __DIGITAL_DOWN_CONVERTER_H__
#include <vector>
#include "interpolator.h"
namespace ddc {
void decimate(std::vector<float> &, unsigned int);
void expand(std::vector<float> &, unsigned int);
void perform_resampling(std::vector<float>, unsigned int, unsigned int);
void generate_filter(std::vector<float> &, unsigned int, unsigned int);
float Sinc(float);
unsigned int mcd(unsigned int, unsigned int);
}
#endif
ddc.cpp
#include "ddc.hpp"
namespace ddc {
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
unsigned int i, gcd = mcd(freq_1, freq_2);
unsigned int downFactor, upFactor;
std::vector<float> filter;
downFactor = freq_1/gcd;
upFactor = freq_2/gcd;
generate_filter(filter, 1024 /* lobi della semi-sinc */, upFactor);
decimate(data, downFactor);
expand(data, upFactor);
interpolate_fft(data, filter);
}
}
main.cpp
#include <vector>
#include "ddc.hpp"
using namespace std;
int main() {
vector<float> data;
// bla bla
ddc::perform_resampling(data, 1000000, 60000);
return 0;
}
Compiling with g++ (linux) I get the following error:
$ make all
g++ -c ddc.cpp -o ddc.o -Wall -O3 -lm -m64
g++ -c main.cpp -o main.o -Wall -O3 -lm -m64
g++ ddc.o main.o -o ../bin/resampler
main.o: In function `main':
main.cpp:(.text.startup+0x255): undefine d reference to
`ddc::perform_resampling(std::vector<float, std::allocator<float> >, unsigned int, unsigned int)'
collect2: ld returned 1 exit status
make: *** [../bin/resampler] Error 1
I'm going out of my mind, please help me! What am I doing wrong? Besides, If I remove ddc:: from the main function, gcc suggests me this:
main.cpp:59:49: note: suggested alternative:
ddc.hpp:24:7: note: ‘ddc::perform_resampling’
You declare a function taking a vector by value as its first argument, then define it taking the vector by reference. This produces a separate overload, and the declared function has no definition. Presumably it should be a reference, so add & to the declaration in the header.
You would get a more useful compiler error if you defined functions outside their namespace:
void ddc::perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
// ^^^^^
// blah blah
}
since it's an error to define a function with a qualified name if it hasn't been declared.
These two are different:
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2)
void perform_resampling(std::vector<float> data, unsigned int freq_1, unsigned int freq_2)
P.S. This shows one good reason to put parameter names in your prototypes, even though they aren't strictly required. With parameter names, you can compare a prototype directly to a definition, and they should match character for character
In your prototype, you are missing &
void perform_resampling(std::vector<float>, unsigned int, unsigned int);
It appears in the definition
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
unsigned int i, gcd = mcd(freq_1, freq_2);
unsigned int downFactor, upFactor;
std::vector<float> filter;
downFactor = freq_1/gcd;
upFactor = freq_2/gcd;
generate_filter(filter, 1024 /* lobi della semi-sinc */, upFactor);
decimate(data, downFactor);
expand(data, upFactor);
interpolate_fft(data, filter);
}

How do I store a function to a variable?

I think they are called functors? (it's been a while)
Basically, I want to store a pointer to a function in a variable, so I can specify what function I want to use from the command line.
all the functions return and take the same values.
unsigned int func_1 (unsigned int var1)
unsigned int func_2 (unsigned int var1)
function_pointer = either of the above?
so then I could call it by going: function_pointer(my_variable)?
EDIT:
as per #larsmans's suggestion, I've gotten this:
Config.h:
class Config
{
public:
unsigned static int (*current_hash_function)(unsigned int);
};
Config.cpp:
#include "Config.h"
#include "hashes.h"
unsigned static int (*current_hash_function)(unsigned int) = kennys_hash_16;
hashes.h:
unsigned int kennys_hash(unsigned int out);
unsigned int kennys_hash_16(unsigned int out);
hashes.cpp:
just implements the functions in the header
main.cpp:
#include "Config.h"
#include "hashes.h"
// in test_network:
unsigned int hashed = Config::current_hash_function(output_binary);
//in main():
else if (strcmp(argv[i], "-kennys_hash_16") == 0)
{
Config::current_hash_function = kennys_hash_16;
}
else if (strcmp(argv[i], "-kennys_hash_8") == 0)
{
Config::current_hash_function = kennys_hash;
}
the error I get:
g++ -o hPif src/main.o src/fann_utils.o src/hashes.o src/Config.o -lfann -L/usr/local/lib
Undefined symbols:
"Config::current_hash_function", referenced from:
test_network() in main.o // the place in the code I've selected to show
auto_test_network_with_random_data(unsigned int, unsigned int, unsigned int)in main.o
generate_data(unsigned int, unsigned int, unsigned int)in main.o
_main in main.o // the place in the code I've selected to show
_main in main.o // the place in the code I've selected to show
generate_train_file() in fann_utils.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: *** [hPif] Error 1
The simplest you can do is
unsigned int (*pFunc)(unsigned int) = func_1;
This is a bare function pointer, which cannot be used to point to anything other than a free function.
You can make it less painful if your compiler supports the C++0x auto keyword:
auto pFunc = func_1;
In any case, you can call the function with
unsigned int result = pFunc(100);
There are many other options that provide generality, for example:
You can use boost::function with any C++ compiler
With a compiler implementing features of C++0x you can use std::function
These can be used to point to any entity that can be invoked with the appropriate signature (it's actually objects that implement an operator() that are called functors).
Update (to address updated question)
Your immediate problem is that you attempt to use Config::current_hash_function (which you declare just fine) but fail to define it.
This defines a global static pointer to a function, unrelated to anything in class Config:
unsigned static int (*current_hash_function)(unsigned int) = kennys_hash_16;
This is what you need instead:
unsigned int (*Config::current_hash_function)(unsigned int) = kennys_hash_16;
From C++11 you can use std::function to store functions. To store function you use it as follsonig:
std::function<return type(parameter type(s))>
as an example here it is:
#include <functional>
#include <iostream>
int fact (int a) {
return a > 1 ? fact (a - 1) * n : 1;
}
int pow (int b, int p) {
return p > 1 ? pow (b, p - 1) * b : b;
}
int main (void) {
std::function<int(int)> factorial = fact;
std::function<int(int, int)> power = pow;
// usage
factorial (5);
power (2, 5);
}
No, these are called function pointers.
unsigned int (*fp)(unsigned int) = func_1;
You could also use function either from the c++0x or from boost.
That would be
boost::function<int(int)>
and then use bind to bind your function to this type.
Have a look here and here
Ok here would be a example. I hope that helps.
int MyFunc1(int i)
{
std::cout << "MyFunc1: " << i << std::endl;
return i;
}
int MyFunc2(int i)
{
std::cout << "MyFunc2: " << i << std::endl;
return i;
}
int main(int /*argc*/, char** /*argv*/)
{
typedef boost::function<int(int)> Function_t;
Function_t myFunc1 = boost::bind(&MyFunc1, _1);
Function_t myFunc2 = boost::bind(&MyFunc2, _1);
myFunc1(5);
myFunc2(6);
}
You can store a function in a variable in c++ in this way
auto function_name = [&](params){
statements
};
auto add = [&](int a,int b){
return a+b;
};
cout<<add(5,6);
typedef unsigned int (*PGNSI)(unsigned int);
PGNSI variable1 = func_1;
PGNSI variable2 = func_2;
unsigned int (* myFuncPointer)(unsigned int) = &func_1;
However, the syntax for function pointers is awful, so it's common to typedef them:
typedef unsigned int (* myFuncPointerType)(unsigned int);
myFuncPointerType fp = &func_1;
IF you have Boost installed, you can also check out Boost Function.