有两个c++程序。一个简单,另一个有点复杂。但都有同样的问题。简单的程序有以下文件。foo.h:
class foo{
static const int array[3];
};
const int foo::array[3] = { 1, 2, 3 }; <-------- Here is the line causing the error.
foo.cc:
#include "foo.h"
main.cc:
#include "foo.h"
int main()
{
}
同时使用以下命令编译和链接:
clang++ -c *.cc -std=c++17
clang++ *.o -o a.out -std=c++17
它报告以下错误:
main.o:(.rodata+0x0): multiple definition of `foo::array'
foo.o:(.rodata+0x0): first defined here
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)
对于复杂系统,具有以下文件. t_a.h:
#pragma once
#include "t_b.h"
class TA : public TB,
public TIT<TB, TA> {
public:
static const char* name() { return "TA"; }
};
t_B.h:
#pragma once
#include "t_r.h"
class TB {
TI<TB> t_i() const { return t_i_; }
private:
template <typename T, typename U>
friend class TIT;
TI<TB> t_i_{TI<TB>::kUkT};
};
t_i.h:
#pragma once
#include <string>
#include <stdint.h>
template <typename BaseT>
class TR;
template <typename BaseT>
class TI {
public:
const std::string& name() const;
int8_t id() const { return id_; }
bool operator==(TI other) const { return id_ == other.id(); }
bool operator!=(TI other) const { return id_ != other.id(); }
static const TI kUkT;
private:
friend class TR<BaseT>;
explicit TI(int8_t id) : id_(id) {}
int8_t id_;
};
template <typename BaseT, typename DerivedT>
class TIT {
public:
static const TI<BaseT> kT;
TIT() {
static_cast<BaseT*>(static_cast<DerivedT*>(this))->t_i_ = kT;
}
static bool classof(const BaseT* obj) { return obj->t_i() == kT; }
};
template <typename BaseT>
TI<BaseT> RST(const std::string& t);
template <typename BaseT, typename DerivedT>
const TI<BaseT> TIT<BaseT, DerivedT>::kT =
RST<BaseT>(DerivedT::name()); <-------- This block of code should cause a similar error, but it does not.
t_r.h:
#pragma once
#include <cassert>
#include <map>
#include <mutex>
#include <string>
#include <vector>
#include "t_i.h"
template <typename BaseT>
class TR {
public:
TR(const TR&) = delete;
TR& operator=(const TR&) = delete;
static TR& GI();
TI<BaseT> RT(const std::string& t);
const std::string& GTN(TI<BaseT> i) const;
private:
TR() = default;
mutable std::mutex mutex_;
std::vector<std::string> names_;
std::map<std::string, int8_t> name_to_id_;
};
template <typename BaseT>
TR<BaseT>& TR<BaseT>::GI() {
static TR<BaseT> r;
return r;
}
template <typename BaseT>
TI<BaseT> TR<BaseT>::RT(const std::string& t) {
std::lock_guard<std::mutex> guard(mutex_);
assert(name_to_id_.find(t) == name_to_id_.end());
assert(names_.size() < static_cast<decltype(names_.size())>(
std::numeric_limits<int8_t>::max()));
int8_t id = static_cast<int8_t>(names_.size());
names_.emplace_back(t);
name_to_id_[t] = id;
return TI<BaseT>(id);
}
template <typename BaseT>
const std::string& TR<BaseT>::GTN(
TI<BaseT> info) const {
std::lock_guard<std::mutex> guard(mutex_);
int8_t id = info.id();
assert(id >= 0);
assert(static_cast<size_t>(id) < names_.size());
return names_[id];
}
template <typename BaseT>
TI<BaseT> RST(const std::string& type) {
return TR<BaseT>::GI().RT(type);
}
template <typename BaseT>
const std::string& TI<BaseT>::name() const {
return TR<BaseT>::GI().GTN(*this);
}
template <typename BaseT>
const TI<BaseT> TI<BaseT>::kUkT =
RST<BaseT>("Uk");
使用_t_i_1.cc:
#include "t_a.h"
TIT<TB, TA> test_class_1;
使用_t_i_2.cc:
#include "t_a.h"
int main() {
TIT<TB, TA> test_class_2;
}
当通过以下命令编译和链接时:
clang++ -c *.cc -std=c++17
clang++ *.o -o a.out -std=c++17
没有出现错误。是什么原因导致两个程序都存在同样的语法错误,而一个报告错误,而另一个没有?有人能解释一下吗?有人能对第二个复杂的程序做一个小的调整,使它也出现同样的错误吗?提前感谢。
2条答案
按热度按时间mbzjlibv1#
这条线
需要在 * one *. cc文件中,而不是在标头中。只需选择一个
c0vxltue2#
C++明确允许模板化实体的多个定义:
basic.def.odr#13:
可以有多个定义
*模板化实体([临时预处理]),
因此,不会导致多重定义错误。