Reputation: 3
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;
}
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?
Upvotes: 0
Views: 388
Reputation: 2515
See the answers for this question.
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;
Alternatively, if you don't want to have to track value declarations through a large project, you can also turn the value
s 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.
Upvotes: 2