C++ tuple linking issue: undefined reference - c++

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

Related

C++ access static constexpr array

I am trying to get some values from an array which is declared in another class. The array has a fixed length and constant elements (I will 100% never modify its values, so that's why I made it constant).
However, when I try to access the first element in the main function, I get a compilation error:
basavyr#Roberts-MacBook-Pro src % g++ -std=c++11 main.cc
Undefined symbols for architecture x86_64:
"Vectors::vec1", referenced from:
_main in main-c29f22.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1
As you can see, I'm compiling on macOS Catalina using clang (latest version).
[Q]:What could be the issue?
Thank you in advance.
Here is the code:
#include <iostream>
class Dimension
{
public:
static constexpr int dim1 = 2;
static constexpr int dim2 = 1;
};
class Vectors
{
public:
static constexpr double vec1[2] = {4.20, 6.9};
};
int main()
{
auto a = Vectors::vec1[0]; //I also tried initializing this to a value rather than just accessing it directly through the class like I did below
std::cout << a << "\n";
std::cout << Vectors::vec1[0] << "\n";
return 0;
}
You're compiling in C++11 mode; you need to provide definition for these constexpr static members at namespace scope. Note that this is not required since c++17.
If a const non-inline (since C++17) static data member or a constexpr static data member (since C++11) is odr-used, a definition at namespace scope is still required, but it cannot have an initializer. This definition is deprecated for constexpr data members (since C++17).
e.g.
class Dimension
{
public:
static constexpr int dim1 = 2;
static constexpr int dim2 = 1;
};
constexpr int Dimension::dim1;
constexpr int Dimension::dim2;
class Vectors
{
public:
static constexpr double vec1[2] = {4.20, 6.9};
};
constexpr double Vectors::vec1[2];

Linker Error in template specialization of a class

I have a header file TimeSeries.h, which has definitions and specializations of default_value template
TimeSeries class has other methods
I included TimeSeries.h file in main.cpp
This is my header file TimeSeries.h, followed by main.cpp
template<typename>
struct default_value;
template<>
struct default_value<int> {
static constexpr int value = 0;
};
template<>
struct default_value<double> {
static constexpr double value = std::numeric_limits<double>::quiet_NaN();
};
template <typename T>
class TimeSeries
{
public:
std::vector<uint64_t> timeUsSinceMid;
std::vector<T> values;
void addValue(uint64_t time, T value)
{
timeUsSinceMid.push_back(time);
values.push_back(value);
}
TimeSeries<T> * sample(uint64_t sampleFreq, uint64_t startTime=0, uint64_t
endTime=86400*1000*1000ULL)
{
//Some code
// I essentially faked a time and a default value push
TimeSeries<T>* newSample = new TimeSeries<T>;
newSample->timeUsSinceMid.push_back(timeUsSinceMid[0]);
newSample->values.push_back(default_value<T>::value);
return newSample;
}
};
Here is main.cpp:
#include<TimeSeries.h>
int main(int argc, const char * argv[]) {
TimeSeries<double> T;
T.addValue(1, 100.0);
T.addValue(2,200.0);
T.addValue(3,300.0);
T.addValue(4,400.0);
TimeSeries<double>* newT = T.sample(2,1,6);
//cout<<*newT<<endl;
return 0;
}
This is the linker error
Undefined symbols for architecture x86_64:
"default_value<double>::value", referenced from:
TimeSeries<double>::sample(unsigned long long, unsigned long long, unsigned long long) in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can anyone please explain why "default_value::value" is undefined?
See the answers for this question.
Using the structure of your posted code
Your template definition defines the object value, but it still needs to be declared.
Don't ask me why, I'm just copying #Pete Becker's answer from the other post (which unfortunately wasn't very detailed). All I know is that the below code now compiles:
template<>
struct default_value<double> {
static constexpr double value = std::numeric_limits<double>::quiet_NaN();
};
// EDIT: inserted line below
constexpr double default_value<double>::value;
Changing the structure a bit
Alternatively, if you don't want to have to track value declarations through a large project, you can also turn the values into in-lined methods, like so: (edit added in constexpr's; also noting that inline is not required & likely doesn't change compiler behavior)
template<>
struct default_value<int> {
// EDIT: changed value to function
static inline constexpr int value() {
return 0;
}
};
template<>
struct default_value<double> {
// EDIT: changed value to function
static inline constexpr double value() {
return std::numeric_limits<double>::quiet_NaN();
}
};
Of course, remember to change your TimeSeries::sample method to use default_value<>::value as a method.

Use of boost coroutine2 without lambdas

I guess this is the first time I couldn't manage to find an already answered question in here, and I could really use some help if anyone have successfully used boost coroutine2 lib without lambdas.
My problem, sumarized:
class worker {
...
void import_data(boost::coroutines2::coroutine
<boost::variant<long, long long, double, std::string> >::push_type& sink) {
...
sink(stol(fieldbuffer));
...
sink(stod(fieldbuffer));
...
sink(fieldbuffer); //Fieldbuffer is a std::string
}
};
I intend to use this as a coroutine from inside another class, that has the task of putting each yielded value in its place, so I tried to instantiate an object:
worker _data_loader;
boost::coroutines2::coroutine<boost::variant<long, long long, double, string>>::pull_type _fieldloader
(boost::bind(&worker::import_data, &_data_loader));
but that wont compile:
/usr/include/boost/bind/mem_fn.hpp:342:23:
error: invalid use of non-static member function of type
‘void (worker::)(boost::coroutines2::detail::push_coroutine<boost::variant<long int, long long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)’
Could someone shed any light in this problem?
This has nothing to do with Boost Coroutine.
It is just about bind with a member function. You forgot to expose the unbound parameter:
boost::bind(&worker::import_data, &_data_loader, _1)
Live On Coliru
#include <boost/coroutine2/all.hpp>
#include <boost/variant.hpp>
#include <boost/bind.hpp>
#include <string>
using V = boost::variant<long, long long, double, std::string>;
using Coro = boost::coroutines2::coroutine<V>;
class worker {
public:
void import_data(Coro::push_type &sink) {
sink(stol(fieldbuffer));
sink(stod(fieldbuffer));
sink(fieldbuffer); // Fieldbuffer is a std::string
}
std::string fieldbuffer = "+042.42";
};
#include <iostream>
int main()
{
worker _data_loader;
Coro::pull_type _fieldloader(boost::bind(&worker::import_data, &_data_loader, _1));
while (_fieldloader) {
std::cout << _fieldloader.get() << "\n";
_fieldloader();
}
}
Prints
42
42.42
+042.42

linking template metaprogramming issue with g++

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.

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.