c++ - 如何检查变量是否派生自类?
问题描述
我想打印多种类型的变量。我创建了一个名为 的类IStringable
,以及一些派生自它的类。在我的PrintVariable
函数中,我想检查参数是否来自IStringable
,如果是,则打印它。
class IStringable {
public:
virtual ~IStringable() { }
virtual std::string ToString() const = 0;
}
class Person : public IStringable {
public:
Person(const std::string name) : _name(name) { }
virtual std::string ToString() const { return _name; }
private:
std::string _name;
}
// This does not work as intended, as I don't know how it could be implemented
template <>
void PrintVariable<IStringable>(const IStringable& var) {
std::cout << var.ToString() << std::endl;
}
int main() {
Person p("Foo");
PrintVariable(p);
}
到目前为止,我只是通过使用std::cout << p.ToString() << std::endl;
来解决这个问题,但我想知道是否有更好的解决方案。
解决方案
您不需要模板:
void PrintVariable(const IStringable& var) {
std::cout << var.ToString() << '\n';
}
只有对PrintVariable
对象可转换为的调用IStringable
是合法的:
Person p("Alice");
struct Bob {} b;
PrintVariable(p); // OK
PrintVariable(b); // ill-formed: no conversion from Bob to const IStringable&
此外,您可以重新设计PrintVariable
为操作员:
std::ostream& operator<<(std::ostream& os, IStringable const& rhs)
{
return os << rhs.ToString();
}
所以你可以写:
Person p("Alice");
std::cout << p << '\n';
从评论中可以看出,OP想要一种记录事物的方法。一个最小的实现是:
#include <string_view>
#include <type_traits>
#include <iostream>
namespace Logger
{
struct IStringable
{
virtual ~IStringable() {}
virtual std::string ToString() const = 0;
};
std::string to_string(IStringable const& v) { return v.ToString(); }
void log(std::string_view const& sv)
{
std::cout << "debug: " << sv << '\n';
}
template<class T, std::enable_if_t<!std::is_convertible_v<T, std::string_view>, int> = 0>
void log(T const& v)
{
using std::to_string;
log(to_string(v));
}
}
这个想法是使用ADL和SFINAE来调用要记录std::to_string
的ISrtingable::ToString
事物,并记录结果字符串。
用法:
class Person : public Logger::IStringable {
public:
Person(const std::string name) : _name(name) { }
virtual std::string ToString() const { return _name; }
private:
std::string _name;
};
int main()
{
Person p("Alice");
double d = 0.0;
const char* c = "Some words";
Logger::log(p);
Logger::log(d);
Logger::log(c);
}
推荐阅读
- java - 当我点击注册按钮时,它的节目“不幸的是项目已停止”
- reactjs - 你如何从 recompose 中读取这个 curry'd 函数……我的脑痛
- oracle - WCF-自定义 oracleDBBinding:ORA-22062:Oracle.DataAccess.Types.OracleDecimal 处的输入字符串 [40,7] 无效
- javascript - 我的列表项从正确的位置开始,但最终溢出 div 顶部
- java - 当我读取由反斜杠组成的字符串时,但在运行时将其视为双黑斜杠并且由于 java 抛出异常:
- hibernate - 如何减去两个日期并转换为年份
- python - 运行程序时如何开始上课?
- python - PySpark:如何按固定日期范围和另一列使用窗口函数计算值列的总和进行分组?
- c# - 具有完全 AES 加密性能问题的数据库
- excel - 单元格范围导出为图像,没有白色边框