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);
}
Related
I am porting some windows code that compiles like would expect under msvc 10, but I am having trouble with it linking under g++ 4.8 and/or clang 3.5.
masks.h
#ifndef MASKS_H
#define MASKS_H
#include <boost/array.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
namespace MASKS
{
// ------------------------------------------------- power function
template<class TYPE, uint32_t Base, uint32_t Power>
struct Pow
{
static const TYPE tmp = Pow<TYPE, Base, Power / 2>::value;
static const TYPE value = (Power % 2 == 0) ? (tmp * tmp) : (Base * tmp * tmp);
};
template<class TYPE, uint32_t Base>
struct Pow<TYPE, Base, 0>
{
static const TYPE value = 1;
};
template<class TYPE, uint32_t Base>
struct Pow<TYPE, Base, 1>
{
static const TYPE value = Base;
};
// ------------------------------------------------- mask function
template<class TYPE, int Val>
struct Mask
{
static const TYPE value = Pow<TYPE, 2, Val>::value - 1;
};
template<class TYPE>
struct Mask<TYPE, 64>
{
static const TYPE value = 0xffffffffffffffff;
};
//#define MASK(z, n, text) (MASKS::Mask<uint64_t, n>::value)
static const boost::array<uint64_t, 4> s_Masks =
boost::assign::list_of<uint64_t>
(MASKS::Mask<uint64_t, 0>::value)
(MASKS::Mask<uint64_t, 1>::value)
(MASKS::Mask<uint64_t, 2>::value)
(MASKS::Mask<uint64_t, 3>::value)
//BOOST_PP_REPEAT_FROM_TO (0, 65, MASK, text)
;
inline uint64_t GetMask (size_t iLen) { return MASKS::s_Masks[iLen]; }
} // namespace MASKS
#endif // MASKS_H
main.c
#include <iostream>
#include "masks.h"
int main (int /*argc*/, char */*argv*/[])
{
std::cout << "63 bit mask: " << std::hex << std::showbase << MASKS::GetMask (63) << std::endl;
return 0;
}
When I compile it will not link and gives the following error:
g++ masks.cpp -o mask -std=c++11 -pedantic -Wall -Wextra
tmp/ccYZ0MMb.o: In function `__static_initialization_and_destruction_0(int, int)':
masks.cpp:(.text+0xd9): undefined reference to `MASKS::Mask<unsigned long long, 0>::value'
masks.cpp:(.text+0xea): undefined reference to `MASKS::Mask<unsigned long long, 1>::value'
masks.cpp:(.text+0xfe): undefined reference to `MASKS::Mask<unsigned long long, 2>::value'
masks.cpp:(.text+0x10f): undefined reference to `MASKS::Mask<unsigned long long, 3>::value'
collect2: error: ld returned 1 exit status
I am not sure what I am forgetting here. I expected the TMP objects/functions to get translated to values by the compiler and stored in the array of masks I am trying to build. I am rusty on my g++ syntax I guess. Can anyone see what I've done wrong?
Thanks.
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.
This week I started to upgrade my knowledge from C to C++, I would like to overload some operators
I have a class called Matrix
#include "lcomatrix.h"
inline Matrix::Matrix(unsigned rows, unsigned cols) :
rows_(rows), cols_(cols)
{
data_ = new double[rows * cols];
}
inline Matrix::~Matrix() {
delete[] data_;
}
inline double& Matrix::operator()(unsigned row, unsigned col) {
return data_[cols_ * row + col];
}
inline double Matrix::operator()(unsigned row, unsigned col) const {
return data_[cols_ * row + col];
}
The content of lcomatrix.h is
#include <iostream>
class Matrix {
public:
Matrix(unsigned rows, unsigned cols);
double& operator()(unsigned row, unsigned col);
double operator()(unsigned row, unsigned col) const;
~Matrix(); // Destructor
Matrix& operator=(Matrix const& m); // Assignment operator
private:
unsigned rows_, cols_;
double* data_;
};
Main.cpp
#include "lcomatrix.h"
#include <iostream>
/*-
* Application entry point.
*/
int main(void) {
Matrix mx(12,12);
//std::cout << mx << std::endl;
return 0;
}
Make file:
CPPFLAGS=-I /path/lcomatrix/
EFLAGS=
all : main.o lcomatrix.o
g++ $(EFLAGS) -o main.out main.o lcomatrix.o
main.o: lcomatrix.o
g++ $(EFLAGS) $(CPPFLAGS) -c main.cpp
lcomatrix.o:
g++ $(EFLAGS) -c /home/robu/UbuntuOne/ChibiOS-RPi/lcomatrix/lcomatrix.cpp
clean:
rm *.o main.out
When I try to build I receive the following link error:
make all
g++ -c /home/robu/UbuntuOne/ChibiOS-RPi/lcomatrix/lcomatrix.cpp
g++ -I /home/robu/UbuntuOne/ChibiOS-RPi/lcomatrix/ -c main.cpp
g++ -o main.out main.o lcomatrix.o
main.o: In function `main':
main.cpp:(.text+0x1b): undefined reference to `Matrix::Matrix(unsigned int, unsigned int)'
main.cpp:(.text+0x2c): undefined reference to `Matrix::~Matrix()'
collect2: error: ld returned 1 exit status
make: *** [all] Error 1
I guess this a really stupid error, but as a beginner I couldn't figure out the solution.
Your method definitions are all inline. In order to inline a function, the compiler needs to see its definition whenever it is compiling the code that uses it.
Either put the function definitions somewhere they can be seen at the point of use - in the header, or in another file #included by Main.cpp - or don't mark them as inline.
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;
}
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.