模板参数子类型的用法(高级情况)
Usage of template parameters subtype (advanced case)
我有几个具有以下继承关系的类:
template <typename ID_t>
class Identifiable {
public:
virtual ID_t unique_ID() const {
return 0;
}
};
template <typename DerivedName>
class SomeBase : public Identifiable<typename DerivedName::ID_t> {
public:
virtual DerivedName & instance() = 0;
};
template <uint16_t SomeParam = 5>
class SomeDerived : public SomeBase<SomeDerived<SomeParam>> {
public:
using ID_t = uint16_t;
SomeDerived & instance() override {
return *this;
}
ID_t unique_ID() const override {
return SomeParam;
}
};
int main() {
std::cout << "Hello, World!n";
SomeDerived<> instance;
std::cout << std::to_string(instance.unique_ID()) << std::endl;
}
但这不会在声明行中使用"类 SomeDerived 中没有名为 ID_t 的类型"进行编译SomeBase
。即使原因很明显,有没有办法在没有此检查的情况下强制编译?或者修复它而不ID_t
作为另一个模板参数传递?
以下是沙盒的链接:cpp.sh/57ox6
您缺少Identifiable
的类型别名:
template <typename ID>
class Identifiable {
public:
using ID_t = ID;
virtual ID_t unique_ID() const {
return 0;
}
};
问题是您尝试在定义SomeDerived::ID_t
之前使用它。
您可以稍微重构类以使其为您工作。
#include <iostream>
#include <string>
template <typename ID>
class Identifiable
{
public:
using ID_t = ID;
virtual ID_t unique_ID() const {
return 0;
}
};
template <typename DerivedName>
class SomeBase
{
public:
virtual DerivedName & instance() = 0;
};
template <uint16_t SomeParam = 5>
class SomeDerived : public Identifiable<uint16_t>,
public SomeBase<SomeDerived<SomeParam>>
{
public:
SomeDerived & instance() override {
return *this;
}
ID_t unique_ID() const override {
return SomeParam;
}
};
int main()
{
std::cout << "Hello, World!n";
SomeDerived<> instance1;
std::cout << std::to_string(instance1.unique_ID()) << std::endl;
SomeDerived<20> instance2;
std::cout << std::to_string(instance2.unique_ID()) << std::endl;
}
输出:
Hello, World!
5
20
即使原因很明显,有没有办法在没有此检查的情况下强制编译?或者修复它而不将ID_t作为另一个模板参数传递?
这不是在没有此检查的情况下强制编译的问题。你想做的事情违反了语言的规则,仅此而已。因此,它是无法编译的格式错误的代码。
换句话说,在SomeBase
中,您尝试使用未完全定义的类型 ( SomeDerived
(。因此,你不能指望DerivedName::ID_t
在那里。而且你不能指望能够告诉你的编译器 - 呃,伙计,忽略C++标准并编译它,不管它是什么。
@R.Sahu 发布了一个有效的解决方法,他的答案,也许是你能得到的最短、最有效的解决方案。
另一种选择是使用特征,如以下示例所示:
#include<cstdint>
#include<iostream>
template <typename T>
struct Identifiable {
using ID_t = T;
virtual ID_t unique_ID() const {
return 0;
}
};
template<typename>
struct SomeTraits;
template <typename DerivedName>
struct SomeBase : public Identifiable<typename SomeTraits<DerivedName>::ID_t> {
virtual DerivedName & instance() = 0;
};
template <uint16_t SomeParam = 5>
struct SomeDerived;
template<uint16_t SomeParam>
struct SomeTraits<SomeDerived<SomeParam>> {
using ID_t = uint16_t;
};
template <uint16_t SomeParam>
struct SomeDerived : public SomeBase<SomeDerived<SomeParam>> {
using ID_t = typename SomeBase<SomeDerived<SomeParam>>::ID_t;
SomeDerived & instance() override {
return *this;
}
ID_t unique_ID() const override {
return SomeParam;
}
};
int main() {
std::cout << "Hello, World!n";
SomeDerived<> instance;
std::cout << std::to_string(instance.unique_ID()) << std::endl;
}
相关文章:
- 在没有太多条件句的情况下,我如何避免被零除
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 函数中堆分配的效果与缺少堆分配的情况
- 在未初始化映射的情况下,将值插入到映射的映射中
- 是默认情况下分配给char数组常量的值
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 如何在不产生任何垃圾的情况下获得C中的像素
- 在已经使用Git的情况下减少编译时间
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 如何在没有信号的情况下从C++执行QML插槽
- 如何在不知道向量大小的情况下输入向量内部的向量?
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 为什么在某些情况下不写入此文件?
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 在没有Xcode的情况下在Mac捆绑包中嵌入框架
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 为什么这个音频包络不能通过开关的情况?
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 模板参数子类型的用法(高级情况)