linking template metaprogramming issue with g++ - templates

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.

Related

C++ tuple linking issue: undefined reference

I suppose that there is something terribly wrong with this code. It will compile but does not get linked.
#include <iostream>
#include <tuple>
class Table_class
{
public:
constexpr static std::tuple<int, unsigned int, unsigned short> table[3]
= {std::make_tuple(1, 2, 3),
std::make_tuple(4, 5, 6),
std::make_tuple(7, 8, 9)};
};
int main()
{
std::cout << std::get<0>(Table_class::table[0]);
return 0;
}
The error that shows up is this:
[31m/tmp/ccDiIuPv.o: In function `main':
file.cpp:(.text+0x5): undefined reference to `Table_class::table'
collect2: error: ld returned 1 exit status
Compilation Failed
How can this be corrected?
It's not terribly wrong. Your code is (will be) perfectly legal in C++17. However, before C++17, static constexpr data members need to be defined outside of class, so find somewhere and add the following definition:
constexpr std::tuple<int, unsigned int, unsigned short> Table_class::table[3];
demo.
As usual, variable definition should not be in a header file.
It's a common source of linking errors.
You have to define the table outside the class definition, to make the linker find it.
A simplified example:
#include <iostream>
#include <tuple>
class Table_class
{
public:
constexpr static std::tuple<int, unsigned int, unsigned short> table = std::make_tuple(1, 2, 3);
};
constexpr std::tuple<int, unsigned int, unsigned short> Table_class::table;
int main()
{
std::cout << std::get<0>(Table_class::table);
return 0;
}

g++/make failing while linking object files

So, I am trying to learn c++ and a little bit about makefiles. However, for some reason I cannot get my files to link properly. The makefile is the following:
OBJS = stl_test.o src/t_stack.o src/matrix_w.o src/matrix.o
stl_test: $(OBJS)
g++ -o stl_test $(OBJS) -lm
.cpp.o:
g++ -c -O -I. $< -o $# -std=c++0x
stl_test.o: include/t_stack.h
src/matrix.o: include/matrix.h
src/matrix_w.o: include/matrix_w.h
src/t_stack.o: include/t_stack.h
include/matrix_w.h: include/matrix.h
touch include/matrix_w.h
include/t_stack.h: include/matrix_w.h include/matrix.h
touch include/t_stack.h
The problem that i am currently having is the following:
touch include/matrix_w.h
touch include/t_stack.h
g++ -c -O -I. stl_test.cpp -o stl_test.o -std=c++0x
g++ -c -O -I. src/t_stack.cpp -o src/t_stack.o -std=c++0x
g++ -c -O -I. src/matrix_w.cpp -o src/matrix_w.o -std=c++0x
g++ -c -O -I. src/matrix.cpp -o src/matrix.o -std=c++0x
g++ -o stl_test stl_test.o src/t_stack.o src/matrix_w.o src/matrix.o -lm
src/t_stack.o: In function `T_stack::pop()':
t_stack.cpp:(.text+0xc9): undefined reference to `Matrix<double>::display() const'
t_stack.cpp:(.text+0xd7): undefined reference to `Matrix<double>::~Matrix()'
src/t_stack.o: In function `T_stack::push_translation(double, double, double)':
t_stack.cpp:(.text+0x1af): undefined reference to `Matrix<double>::Matrix(int, int, double*)'
t_stack.cpp:(.text+0x239): undefined reference to `Matrix<double>::multiply(Matrix<double>*) const'
src/t_stack.o: In function `T_stack::push_scaling(double, double, double)':
t_stack.cpp:(.text+0x33f): undefined reference to `Matrix<double>::Matrix(int, int, double*)'
t_stack.cpp:(.text+0x3c9): undefined reference to `Matrix<double>::multiply(Matrix<double>*) const'
src/t_stack.o: In function `T_stack::T_stack()':
t_stack.cpp:(.text+0x4f4): undefined reference to `Matrix<double>::Matrix(int, int, double*)'
t_stack.cpp:(.text+0x516): undefined reference to `Matrix<double>::copy() const'
src/t_stack.o: In function `T_stack::~T_stack()':
t_stack.cpp:(.text+0x64c): undefined reference to `Matrix<double>::display() const'
t_stack.cpp:(.text+0x65a): undefined reference to `Matrix<double>::~Matrix()'
t_stack.cpp:(.text+0x74f): undefined reference to `Matrix<double>::display() const'
collect2: ld returned 1 exit status
make: *** [stl_test] Error 1
I am not entirely sure what the problem is. I tried changing the order of the files in the g++ command but that didnt work either. I have tried checking the headers of the files and I think they are correct but I have posted fragments here anyways:
stltest.cpp
#include <iostream>
#include "include/t_stack.h"
using namespace std;
int main(void) {
......
matrix.h
#ifndef _MATRIX_
#define _MATRIX_
#include <iostream>
using namespace std;
......
matrix_w.h
#ifndef _MATRIX_W_
#define _MATRIX_W_
#include "include/matrix.h"
class Matrix_w {
......
t_stack.h
#ifndef _T_STACK_H_
#define _T_STACK_H_
#include <list>
#include <stack>
#include <iostream>
#include "include/matrix.h"
#include "include/matrix_w.h"
using namespace std;
class T_stack {
private:
// matrix stack
stack<Matrix_w*, list<Matrix_w* > >* m_stack;
// inverse transform list
list<Matrix<double>* >* t_list;
public:
T_stack();
void pop();
void push_translation(double tx, double ty, double tz);
void push_scaling(double sx, double sy, double sz);
int size() const;
~T_stack();
};
#endif
Any ideas what the problem might be? Thanks!
Just in case, here is the implementation of the methods that it complains about (the file is called matrix.cpp)..
#include "include/matrix.h"
using namespace std;
template <typename T>
Matrix<T>::~Matrix() {
delete data;
}
template <typename T>
Matrix<T>::Matrix(int width, int height) {
this->height = height;
this->width = width;
this->data = new T[height*width];
}
template <typename T>
Matrix<T>::Matrix(int width, int height, T* data) {
this->height = height;
this->width = width;
this->data = new T[height*width];
int i;
//may be able to speed this up by using memcpy
// Not sure whether this is a good idea anyways
for(i=0; i < height*width; i++) {
this->data[i] = data[i];
}
}
template <typename T>
T Matrix<T>::at(int x, int y) const {
#ifdef __DEBUG
if(x < width && y < height) {
return data[y*width + x];
} else {
throw 1;
}
#else
return data[y*width + x];
#endif
}
template <typename T>
void Matrix<T>::set(int x, int y, T val) {
#ifdef __DEBUG
if(x < width && y < height) {
data[y*width + x] = val;
} else {
throw 1;
}
#else
data[y*width + x] = val;
#endif
}
//this function is just for convenience but it should only work
//when T is some number type ----ASK!!
template <typename T>
void Matrix<T>::display() const {
int i, j;
cout << "[" << endl;
for(i=0; i<height; i++) {
for(j=0; j<width; j++) {
cout << " " << data[i*width + j];
}
cout << endl;
}
cout << "]" << endl;
}
template <typename T>
Matrix<T>* Matrix<T>::multiply(Matrix<T>* other) const {
#ifdef __DEBUG
if(other->height != width) {
throw 1;
}
#endif
T* res = new T[other->width*height];
int i,j,k;
T sum;
for(i=0; i<height; i++) {
for(j=0; j<other->width; j++) {
sum = 0;
for(k=0; k<width; k++) {
sum += other->data[k*other->width+j]*data[i*width+k];
}
res[i*other->width + j] = sum;
}
}
return new Matrix<double>(other->width, height, res);
}
template <typename T>
Matrix<T>* Matrix<T>::copy() const {
return new Matrix<T>(width, height, data);
}
When you have a template class or functions, the functions should be inline, and the body should be in the header file, in the class or outside with inline keyword in the class.
The difference is that, unlike regular class, the compiler is compiling the class for each type you are using as the template type.
If you are not using it at all, the file won't be compiled even once.
In several compilers your code will work even if it split to h and cpp. but you can't count on it.
I see, it would be typical to implement your template as inline functions. You can, however, use an explicit instantiation of the template in your matrix.cpp file. At the bottom, after the definitions, you could try to add:
template class Matrix<double>;
If you're not using precompiled headers, this actually might make a lot of sense. Also, it can go pretty much anywhere I think, but you can only have one of those statements per program, if you instantiate a Matrix in two places it may or may not work.

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);
}

constexpr different exception specifier when splitting definition and declaration

I have the following test piece of code tested on gcc 4.7.2:
#include <iostream>
#include <type_traits>
#ifdef REMOVE_CONSTEXPR_NOEXCEPT
# define CONSTEXPR_NOEXCEPT
#else
# define CONSTEXPR_NOEXCEPT noexcept
#endif
class ConstExpr {
public:
// Some constructors
private:
// Some member data
public:
// Cannot split the declaration if noexcept
static constexpr unsigned int Int(unsigned int i) CONSTEXPR_NOEXCEPT
#ifndef SPLIT_CONSTEXPR_DECLARATION
{
return i;
}
#else
;
#endif
};
#ifdef SPLIT_CONSTEXPR_DECLARATION
constexpr unsigned int ConstExpr::Int(unsigned int i) CONSTEXPR_NOEXCEPT {
return i;
}
#endif
class NoConstExpr {
public:
// Some constructors
private:
// Some member data
public:
// Cannot split the declaration if noexcept
static unsigned int Int(unsigned int i) noexcept;
};
// It's OK on normal functions
inline unsigned int NoConstExpr::Int(unsigned int i) noexcept {
return i;
}
int main()
{
std::cout << "ConstExpr: " << std::integral_constant<unsigned int,
ConstExpr::Int(5)>::value << std::endl;
std::cout << "NoConstExpr: " << NoConstExpr::Int(5) << std::endl;
}
I get the following compilation output:
[matt test] g++ -std=c++11 main.cpp && ./a.out
ConstExpr: 5
NoConstExpr: 5
[matt test] g++ -std=c++11 main.cpp -DSPLIT_CONSTEXPR_DECLARATION && ./a.out
main.cpp:28:55: error: declaration of ‘static constexpr unsigned int ConstExpr::Int(unsigned int)’ has a different exception specifier
main.cpp:17:33: error: from previous declaration ‘static constexpr unsigned int ConstExpr::Int(unsigned int) noexcept (true)’
[matt test] g++ -std=c++11 main.cpp -DSPLIT_CONSTEXPR_DECLARATION -DREMOVE_CONSTEXPR_NOEXCEPT && ./a.out
ConstExpr: 5
NoConstExpr: 5
So my question is: Is it part of the C++11 spec to be able to split the definition and declaration of constexpr functions or is this a gcc bug?
Looks like the gcc bug solves this in 4.8.1

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.