提问人:barony002 提问时间:11/6/2023 更新时间:11/6/2023 访问量:70
从虚拟类继承的类的显式专用化
explicit specialization of a class that inherits from a virtual class
问:
我有一个虚拟类,以及一个实现虚拟函数的继承类BASE
BOX_str
class BASE {
public:
virtual ~BASE() {};
virtual std::vector<int> custom_int() const = 0;
virtual std::vector<double> custom_double() const = 0;
};
struct BOX_str final : public BASE {
template <typename ...Args>
BOX_str(Args... args) : base(std::forward<Args>(args)...) {}
std::string base;
std::vector<int> custom_int() const {
return custom_vec<int>(base);
}
std::vector<double> custom_double() const {
return custom_vec<double>(base);
}
template <typename NUM>
std::vector<NUM> custom_vec(const std::string& s) const {
return {32, 62};
}
};
但是除了函数之外,所有类内容在类似类中都是通用的,BOX_str
custom_vec()
所以我试着做一个模板类BOX
template <typename T>
struct BOX : public virtual BASE {
template <typename ...Args>
BOX(Args... args) : base(std::forward<Args>(args)...) {}
T base;
std::vector<int> custom_int() const {
return custom_vec<int>(base);
}
std::vector<double> custom_double() const {
return custom_vec<double>(base);
}
template <typename NUM>
std::vector<NUM> custom_vec(const T&) const;
};
并留待以后针对每个显式专业化实施custom_vec()
BOX
template <>
struct BOX<std::string> {
template <typename NUM>
std::vector<NUM> custom_vec(const std::string& s) const {
return {42, 52};
}
};
然后我尝试测试类
int main() {
std::string mystr{ "abcd" };
BASE* v1 = static_cast<BASE*>(new BOX<std::string>(mystr));
BASE* v2 = static_cast<BASE*>(new BOX_str(mystr));
}
v2
没有提出任何错误,但确实: ,这意味着 的显式专用化无法访问其构造函数以及 的所有内容。v1
excess elements in struct initializer
BOX
BOX
我被困住了,无法弄清楚如何正确实现该类,以便它以通用方式工作。将不胜感激。BOX
BOX_str
答:
1赞
Kozydot
11/6/2023
#1
您需要在专业化中再次提供类的完整定义,而不仅仅是函数:BOX
custom_vec()
template <>
struct BOX<std::string> : public virtual BASE {
BOX(const std::string& s) : base(s) {}
std::string base;
std::vector<int> custom_int() const {
return custom_vec<int>(base);
}
std::vector<double> custom_double() const {
return custom_vec<double>(base);
}
template <typename NUM>
std::vector<NUM> custom_vec(const std::string& s) const {
return {42, 52};
}
};
评论
0赞
barony002
11/6/2023
这就是我试图避免的,所有 s 内容的定义,除了在类之间更改的函数之外,它是BOX
custom_vec()
0赞
Kozydot
11/6/2023
正如您尝试的那样,在类的专用版本中定义方法将不起作用。当您将类专用化为 时,您正在创建一个全新的类,该类不会从原始模板继承任何内容。这就是构造函数和其他方法在专用类中不可用的原因。custom_vec()
BOX
BOX
std::string
BOX
BOX<std::string>
2赞
YSC
11/6/2023
#2
与往常一样,任何问题*都可以通过额外的抽象层来解决:
define 调用一个尚未定义的:BOX::custom_vec
::custom_vec
template <typename T>
struct BOX : public virtual BASE {
// [...]
template <typename NUM>
std::vector<NUM> custom_vec(const T& v) const {
return ::custom_vec<T, NUM>{}(v);
}
然后,提供一个可以专门化并完全重新定义的结构,而不会无用的代码重复:
template<class BoxT, class BoxN>
struct custom_vec {};
template<>
struct custom_vec<std::string, int>
{ std::vector<int> operator()(std::string const&) const { return {42, 52}; } };
template<>
struct custom_vec<std::string, double>
{ std::vector<double> operator()(std::string const&) const { return {1.618, 3.14}; } };
*除了有太多的抽象层
评论
0赞
barony002
11/6/2023
谢谢你的解决方案,空的双冒号是什么意思?return ::custom_vec<T, NUM>{}(v)
0赞
YSC
11/6/2023
这是“运算符”的范围。它使名称查找从不限定名称查找切换到限定名称查找。在这里,开关的作用是从全局命名空间而不是 .custom_vec
BOX::custom_vec
评论
BASE
BASE