Вам не нужен шаблон:
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);
}
Демонстрация: https://coliru.stacked -crooked.com / a / 77e19e87c9d4780d