【问题标题】:Linker Error in template specialization of a class类的模板特化中的链接器错误
【发布时间】:2018-08-19 21:57:10
【问题描述】:
  • 我有一个头文件 TimeSeries.h,它有 default_value 模板的定义和特化
  • TimeSeries 类还有其他方法
  • 我在 main.cpp 中包含了 TimeSeries.h 文件

这是我的头文件TimeSeries.h,后面是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;
                }
            };

这里是 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)

谁能解释一下为什么“default_value::value”是未定义的?

【问题讨论】:

  • 你能把主要和标题分开吗?
  • 好的!我将在这里定义其他需要的方法,并将header和main分开。
  • push_back 使用参考,你 odr-使用那些 static const。因此需要定义。
  • 我听不懂@li

标签: c++ c++11 templates linker-errors


【解决方案1】:

查看this question的答案。

使用您发布的代码的结构

您的模板定义定义对象value,但它仍然需要是declared。 不要问我为什么,我只是从另一篇文章中复制@Pete Becker 的答案(不幸的是,这不是很详细)。我只知道下面的代码现在可以编译:

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;

稍微改变结构

或者,如果您不想通过大型项目跟踪值声明,您也可以将values 转换为内联方法,如下所示:(edit 添加在constexpr 中;还注意到inline 不是必需的并且可能不会改变编译器行为)

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

当然,请记住将您的TimeSeries::sample 方法更改为使用default_value&lt;&gt;::value 作为方法。

【讨论】:

  • 它有效。这真的很奇怪。我知道静态成员应该在声明之后在类之外定义,而不是相反。我会阅读更多关于它的内容并发布我发现的任何内容。谢谢@Shillard。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 2014-10-21
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多