Can I use templates instead of macros for Exception class creation? - c++

I often want to define new 'Exception' classes, but need to have an appropriate constructor defined because constructors aren't inherited.
class MyException : public Exception
{
public:
MyException (const UString Msg) : Exception(Msg)
{
};
}
Typedefs don't work for this, because they are simply aliases, not new classes. Currently, to avoid repeating this trivial boilerplate, I use a #define which does the donkeywork.
#define TEXCEPTION(T) class T : public Exception \
{ \
public:\
T(const UString Msg) : Exception(Msg) {}; \
}
...
TEXCEPTION(MyException);
But I keep wondering if there's a better way of achieving this - maybe with templates, or some new C++0x feature

If you really want to have new classes derived from Exception, as opposed to having a template parameterized by a parameter, there is no way around writing your own constructor that just delegates the arguments without using a macro. C++0x will have the ability what you need by using something like
class MyException : public Exception
{
public:
using Exception::Exception;
};
You can read about the details of that (seem to have quite a bit of extra rules) in 12.9 "Inheriting Constructors" in the latest draft of C++0x.
In the meantime, i would recommend a policy based design (made small text, because the OP accepted the above, and not this policy stuff):
// deriving from Impl first is crucial, so it's built first
// before Exception and its Ctor can be used.
template<typename Impl>
struct ExceptionT : Impl, Exception {
// taking a tuple with the arguments.
ExceptionT(arg_types const& t = arg_types())
:Exception(Impl::Ctor(t)) { }
// taking a string. plain old stuff
ExceptionT(std::string const& s):Exception(Impl::Ctor(s)) { }
};
struct ExceptionDefImpl {
typedef boost::tuple<> arg_types;
// user defined ctor args can be done using a tuple
std::string Ctor(arg_types const& s) {
return std::string();
}
std::string const& Ctor(std::string const& s) {
return s;
}
};
// will inherit Ctor modifier from DefImpl.
struct MemoryLost : ExceptionDefImpl {
typedef boost::tuple<int> arg_types;
std::string Ctor(arg_types const& s) {
std::ostringstream os;
os << "Only " << get<0>(s) << " bytes left!";
return os.str();
}
int getLeftBytes() const { return leftBytes; }
private:
int leftBytes;
};
struct StackOverflow : ExceptionDefImpl { };
// alias for the common exceptions
typedef ExceptionT<MemoryLost> MemoryLostError;
typedef ExceptionT<StackOverflow> StackOverflowError;
void throws_mem() {
throw MemoryLostError(boost::make_tuple(5));
}
void throws_stack() { throw StackOverflowError(); }
int main() {
try { throws_mem(); }
catch(MemoryListError &m) { std::cout << "Left: " << m.getLeftBytes(); }
catch(StackOverflowError &m) { std::cout << "Stackoverflow happened"; }
}

You could parameterize your template class with an integer:
#include <iostream>
#include <string>
using namespace std;
enum ExceptionId {
EXCEPTION_FOO,
EXCEPTION_BAR
};
class Exception {
string msg_;
public:
Exception(const string& msg) : msg_(msg) { }
void print() { cout << msg_ << endl; }
};
template <int T>
class TException : public Exception {
public:
TException(const string& msg) : Exception(msg) {};
};
void
foo()
{
throw TException<EXCEPTION_FOO>("foo");
}
void
bar()
{
throw TException<EXCEPTION_BAR>("bar");
}
int
main(int argc, char *argv[])
{
try {
foo();
} catch (TException<EXCEPTION_FOO>& e) {
e.print();
};
try {
bar();
} catch (TException<EXCEPTION_BAR>& e) {
e.print();
};
return 0;
}
Although, I don't see why you would favor this over using a single class with an internal enumeration that is set/read at runtime:
class TException {
public:
enum Type { FOO, BAR };
TException(Type type, const string& msg) : Exception(msg), type_(type) {}
Type type() const { return type_; }
private:
Type type_;
};
Then just switch on the type when you catch a TException...

// You could put this in a different scope so it doesn't clutter your namespaces.
template<struct S> // Make S different for different exceptions.
class NewException :
public Exception
{
public:
NewException(const UString Msg) :
Exception(Msg)
{
}
};
// Create some new exceptions
struct MyExceptionStruct; typedef NewException<MyExceptionStruct> MyException;
struct YourExceptionStruct; typedef NewException<YourExceptionStruct> YourException;
struct OurExceptionStruct; typedef NewException<OurExceptionStruct> OurException;
// Or use a helper macro (which kinda defeats the purpose =])
#define MAKE_EXCEPTION(name) struct name##Struct; typedef NewException<name##Struct> name;
MAKE_EXCEPTION(MyException);
MAKE_EXCEPTION(YourException);
MAKE_EXCEPTION(OurException);
// Now use 'em
throw new MyException(":(");

Related

Resolving overloading ambiguity with multiple inheritance of base class templates in C++

Let's say I'm trying to create a Combine class that will be derived from the given base classes.
template<typename ...Bases>
class Combine : public Bases... {};
And this works fine. For example, if I have class Foo and class Bar then class Combine<Foo, Bar> will implement all the methods from Foo and Bar. At least I thought so until I tried this:
struct ContainerProvider {
std::vector<int> container{1, 2, 3};
};
struct ConstGetter : public virtual ContainerProvider {
[[nodiscard]] const int &get(int index) const {
return container[index];
}
};
struct MutableGetter : public virtual ContainerProvider {
int &get(int index) {
return container[index];
}
};
template<typename ...Bases>
class Combine : public Bases... {};
int main() {
Combine<ConstGetter, MutableGetter> container;
container.get(1); // Member 'get' found in multiple base classes of different types
}
In normal situations, I would just use using Super::method;, but here I don't know the names of derived methods. In a perfect world, I could use something like this:
template<typename ...Bases>
class Combine : public Bases... {
using Bases::* ...;
};
But C++ does not allow this.
Is it possible to implement my Combine class somehow? I'm pretty sure the compiler can get all the information to resolve this edge case, but I have no idea how to provide it to make it work.
Curious problem since get() defined only in one class would work perfectly, but in two? Error? I was curious if there might be a core language defect since this problem seems solvable by the compiler, but I didn't see any (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html).
The ideal solution would probably be for MutableGetter to inherit from ConstGetter since, logically, a getter that allows mutation should also allow grabbing non-mutable versions.
struct MutableGetter : public ConstGetter {
using ConstGetter::get;
int &get(int index) {
return container[index];
}
};
Here's the closest I could get:
#include <iostream>
#include <vector>
struct ContainerProvider {
std::vector<int> container{1, 2, 3};
};
struct ConstGetter : public virtual ContainerProvider {
[[nodiscard]] const int &get(int index) const {
std::cout << "CONST" << std::endl;
return container[index];
}
};
struct MutableGetter : public virtual ContainerProvider {
int &get(int index) {
std::cout << "NON-CONST" << std::endl;
return container[index];
}
};
template <typename... Bases>
class Combine;
template <typename B1, typename B2, typename... Bases>
struct Combine<B1, B2, Bases...> : public B1, public Combine<B2, Bases...> {
using B1::get;
using Combine<B2, Bases...>::get;
};
template<typename B>
struct Combine<B> : B {
using B::get;
};
int main() {
Combine<ConstGetter, MutableGetter> container;
std::cout << container.get(0) << std::endl; // non-const
const auto &const_container = container;
std::cout << const_container.get(0) << std::endl; // const
}
It really sucks for the Combine to have to know what member functions its parents expose, though. I found one partial solution if you're willing to drop the idea of member functions and occasionally do a cast...: Use friend functions
#include <iostream>
#include <vector>
struct ContainerProvider {
std::vector<int> container{1, 2, 3};
};
class ConstGetter : public virtual ContainerProvider {
[[nodiscard]] const int &get(int index) const {
std::cout << "CONST" << std::endl;
return container[index];
}
friend [[nodiscard]] const int& get(const ConstGetter &self, int i) { return self.get(i); }
};
class MutableGetter : public virtual ContainerProvider {
int &get(int index) {
std::cout << "NON-CONST" << std::endl;
return container[index];
}
friend [[nodiscard]] const int &get(MutableGetter &self, int i) {
return self.get(i);
}
};
template <typename... Bases>
class Combine : public Bases... {};
int main() {
Combine<ConstGetter, MutableGetter> container;
std::cout << get((MutableGetter&)container, 0) << std::endl;
const auto &const_container = container;
std::cout << get(const_container, 0) << std::endl;
}
I imagine that renaming ConstGetter::get() to ConstGetter::const_get is not an option? However, this compiles: container.ConstGetter::get(); container.MutableGetter::get();, check it here
As of why overload resolution doesn't work across classes, you could check
this old post
and the answer of this question.

Which pattern to generify instantiation of objects that have different Ctor arguments

I would like to construct a robot with or without a tool, a mobile base, and other parts. As I want to automatize the configuration of the parts, I have a class Robot with the parts as template arguments
For instance, in the code below, the code will build as long as we use tools that have the same constructor signature as ToolInterface. It does build with a Screwdriver but does not with a Gripper.
#include <iostream>
#include <string>
class BaseRobot
{
public:
BaseRobot(){};
};
class ToolInterface
{
public:
ToolInterface(BaseRobot* _base, std::string _name):name{_name}{/*register _base*/};
std::string name;
bool param_1;
char param_2;
};
template<class T, class... Args>
constexpr T* construct(Args... args)
{
if constexpr (std::is_same<T, nullptr_t>::value)
{
return nullptr;
}
else
{
return new T(args...);
}
};
template<class Tool>
class Robot : public BaseRobot
{
protected:
Tool* tool;
public:
Robot():tool(construct<Tool>(this, "tool")){ // <--- here is my problem !!
if constexpr (! std::is_same<Tool, nullptr_t>::value)
{
//do stuff on/with tool->param_1, tool->param_2, ...
std::cout << "tool configured" << std::endl;
}
else
std::cout << "no tool" << std::endl;
};
};
class Screwdriver: public ToolInterface
{
public:
Screwdriver(BaseRobot* _base, std::string _name):ToolInterface(_base, _name){};
};
class Gripper: public ToolInterface
{
public:
Gripper(BaseRobot* _base, std::string _name, bool _reversed):
ToolInterface(_base, _name)
,reversed{_reversed}{};
bool reversed;
};
int main()
{
Robot<Screwdriver> robot_screwdriver;
Robot<nullptr_t> robot_null;
//Robot<Gripper> robot_gripper; //does not build
return 0;
}
Here are some ideas :
using a ToolConfig struct that is passed as an argument of Tools. If a tool requires more arguments, one should subclass ToolConfig and cast it into the tool constructor (see below): damn, that looks cumbersome and ugly!
enforce inherited ToolInterface classes Ctor signature: some tools must have a different Ctor signature
using a variadic template to pass args into the template: not reasonable because, in the end, I want something like template<class Tool1, class Tool2, class MobileBase, class Camera> class Robot
solution 1 would look like
struct ToolConfig
{
std::string name;
};
struct GripperConfig : public ToolConfig
{
bool reversed;
};
class Gripper : public ToolInterface
{
public:
Gripper(ToolConfig& _config):
ToolInterface(_config)
,reversed{static_cast<GripperConfig&>(_config).reversed}{};
bool reversed;
};
Do you have a magic pattern to solve my problem? Is my pattern wrong?
You could also use tuple instead of struct, not ideal but this works as well:
#include <iostream>
#include <string>
#include <tuple>
class BaseRobot
{
public:
BaseRobot() {};
};
class ToolInterface
{
public:
ToolInterface(std::string _name) :name{ _name } {/*register _base*/ };
std::string name;
bool param_1;
char param_2;
};
template <typename T, typename ... Types, std::size_t ... Indices>
constexpr T* apply_impl(const std::tuple<Types...>& tuple, std::index_sequence<Indices...>)
{
return new T(std::get<Indices>(tuple)...);
}
template <typename T, typename ... Types>
constexpr T* apply(const std::tuple<Types...>& tuple)
{
return apply_impl<T>(tuple, std::index_sequence_for<Types...>());
}
template<class T, class... Args>
constexpr T* construct(std::tuple<Args...> args)
{
if constexpr (std::is_same<T, nullptr_t>::value)
{
return nullptr;
}
else
{
return apply<T>(args);
}
}
template<class Tool>
class Robot : public BaseRobot
{
protected:
Tool* tool;
public:
template<class ...Args1> //, class ...Args2>
Robot(std::tuple<Args1...> p1): // , std::tuple<Args2...> p2):
tool(construct<Tool>(p1))
{ // <--- here is my problem !!
if constexpr (!std::is_same<Tool, nullptr_t>::value)
{
//do stuff on/with tool->param_1, tool->param_2, ...
std::cout << "tool configured" << std::endl;
}
else
std::cout << "no tool" << std::endl;
};
};
class Screwdriver : public ToolInterface
{
public:
Screwdriver(std::string _name) :ToolInterface(_name) {};
};
class Gripper : public ToolInterface
{
public:
Gripper(std::string _name, bool _reversed) :
ToolInterface(_name)
, reversed{ _reversed }{};
bool reversed;
};
int main()
{
using p1 = std::tuple<std::string>;
Robot<Screwdriver> robot_screwdriver(p1{"sdvr"});
return 0;
}
Could be improved I agree.
You could pass factory lambdas that generate your tools in the initializer.
template<typename Func>
Robot(Func f):tool(f(this, "tool")){ // <--- here is my problem !!
if constexpr (! std::is_same<Tool, std::nullptr_t>::value)
{
//do stuff on/with tool->param_1, tool->param_2, ...
std::cout << "tool configured" << std::endl;
}
else
std::cout << "no tool" << std::endl;
};
The call site would look like this:
Robot<Screwdriver> robot_screwdriver([](auto... args){ return new Screwdriver(args...); });
Robot<std::nullptr_t> robot_null([](auto...){ return nullptr; });
Robot<Gripper> robot_gripper([](auto... args){ return new Gripper(args..., true); });
Not exactly beautiful, but it works.
See here for a full example. Does this solve your problem?
If you can use c++17, you can add a class template deduction guide to reduce some of the redundancy at the call site.

Template functions by index in C++

Suppose I have a class in C++11 like this:
class Something
{
...
private:
class1* a;
class2* b;
class3* c;
public:
class1* reada() { return a; }
class2* readb() { return b; }
class3* readc() { return c; }
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
}
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
Something like this maybe?
class Something
{
...
private:
templateContainer = {class1*,class2*,class3*}
template<thing in templateContainer>
thing variableOfTypeThing;
public:
template<thing in templateContainer>
<thing> read() {return variableOfTypeThing<thing>;}
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
As you can tell from the example, I'm confused.
Basically, I have a class which acts as a container for guaranteed unique class variables (no class1 A; class1 B)
Some function groups for the class are almost identical some function groups are highly varied. It would be great for future people to only have to modify the different parts of the class and get the rest from the templates.
I thought maybe there would be a way by splitting this class up into lots of classes and stuffing them into an array of void pointers, but that seems unwise.
Suggestions?
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
You could encapsulate the user defined classes in a thin wrapper class with a read() function that returns the contained instance. Adding a user defined class to Something would then be done by inheriting wrapper<user_defined_class>.
Basically, I have a class which acts as a container for guaranteed unique class variables
Inheriting this wrapper prevents you from including the same class twice so it could possibly be a way forward:
#include <iostream>
// the "thing" wrapper
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
private:
T variable;
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : thing<int>,
thing<double>,
thing<user_defined>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : thing<user_defined>(val) {}
Something() : Something("") {} // default ctor
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
Edit: It doesn't fulfill the index part of your question though. You access it using the type you'd like to get() as a tag. You basically build a very rudimentary tuple I guess.
Code based on #Ted Lyngmo's answer:
#include <iostream>
#include <string>
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
protected:
T variable;
};
template<typename ...Ts>
struct things : thing<Ts>... {
template<class... SubTs>
things(thing<SubTs>&&... ts) : thing<SubTs>(std::move(ts))... {}
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
struct non_default {
non_default() = delete;
non_default(int) {}
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : public things<int, double, user_defined, non_default>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : things(thing<user_defined>(val), thing<non_default>(0)) {}
Something() : Something("") {} // default ctor
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}

Calling parametrised method on list items with different template parameters

I'm trying to store and manipulate a list of template class objects with different parameter types; the template class has two parametrised methods, one returning the parameter type and a void one accepting it as input.
More specifically, I have a template class defined as follows:
template<typename T>
class Test
{
public:
virtual T a() = 0;
virtual void b(T t) = 0;
};
And different specifications of it, such as:
class TestInt : public Test<int>
{
public:
int a() {
return 1;
}
void b(int t) {
std::cout << t << std::endl;
}
};
class TestString : public Test<std::string>
{
public:
std::string a() {
return "test";
}
void b(std::string t) {
std::cout << t << std::endl;
}
};
I'd like to be able to store in one single list different objects of both TestInt and TestString type and loop through it calling one method as input for the other, as in:
for (auto it = list.begin(); it != list.end(); ++it)
(*it)->b((*it)->a());
I've looked into boost::any but I'm unable to cast the iterator to the specific class, because I don't know the specific parameter type of each stored object. Maybe this cannot be done in a statically typed language as C++, but I was wondering whether there could be a way around it.
Just for the sake of completeness, I'll add that my overall aim is to develop a "parametrised observer", namely being able to define an observer (as with the Observer Pattern) with different parameters: the Test class is the observer class, while the list of different types of observers that I'm trying to properly define is stored within the subject class, which notifies them all through the two methods a() and b().
The virtuals have actually no meaning here, since for each T the signatures are distinct.
So it seems you have Yet Another version of the eternal "how can we emulate virtual functions templates" or "how to create an interface without virtual functions":
Generating an interface without virtual functions?
How to achieve "virtual template function" in C++
The first one basically contains an idea that you could employ here.
Here's an idea of what I'd do:
Live On Coliru
#include <algorithm>
#include <iostream>
namespace mytypes {
template <typename T>
struct Test {
T a() const;
void b(T t) { std::cout << t << std::endl; }
};
template <> int Test<int>::a() const { return 1; }
template <> std::string Test<std::string>::a() const { return "test"; }
using TestInt = Test<int>;
using TestString = Test<std::string>;
}
#include <boost/variant.hpp>
namespace mytypes {
using Value = boost::variant<int, std::string>;
namespace detail {
struct a_f : boost::static_visitor<Value> {
template <typename T>
Value operator()(Test<T> const& o) const { return o.a(); }
};
struct b_f : boost::static_visitor<> {
template <typename T>
void operator()(Test<T>& o, T const& v) const { o.b(v); }
template <typename T, typename V>
void operator()(Test<T>&, V const&) const {
throw std::runtime_error(std::string("type mismatch: ") + __PRETTY_FUNCTION__);
}
};
}
template <typename O>
Value a(O const& obj) {
return boost::apply_visitor(detail::a_f{}, obj);
}
template <typename O, typename V>
void b(O& obj, V const& v) {
boost::apply_visitor(detail::b_f{}, obj, v);
}
}
#include <vector>
int main()
{
using namespace mytypes;
using AnyTest = boost::variant<TestInt, TestString>;
std::vector<AnyTest> list{TestInt(), TestString(), TestInt(), TestString()};
for (auto it = list.begin(); it != list.end(); ++it)
b(*it, a(*it));
}
This prints
1
test
1
test
Bonus Points
If you insist, you can wrap the AnyTest variant into a proper class and have a() and b(...) member functions on that:
Live On Coliru
int main()
{
using namespace mytypes;
std::vector<AnyTest> list{AnyTest(TestInt()), AnyTest(TestString()), AnyTest(TestInt()), AnyTest(TestString())};
for (auto it = list.begin(); it != list.end(); ++it)
it->b(it->a());
}
Expanding on my comment above, the simplest what I can currently think of to achieve what you are trying to do - at least as I understood it from your example code - is the following:
/* Interface for your container, better not forget the destructor! */
struct Test {
virtual void operate(void) = 0;
virtual ~Test() {}
};
/* Implementation hiding actual type */
template<typename T>
struct TestImpl : public T, public Test {
void operate(void) {
T::b(T::a());
}
};
/* Actual code as template policies */
struct IntTest {
int a(void) {
return 42;
}
void b(int value) {
std::cout << value << std::endl;
}
};
struct StringTest {
std::string a(void) {
return "Life? Don't talk to me about life.";
}
void b(std::string value) {
std::cout << value << std::endl;
}
};
You would then need to create a container for objects of class Test and fill it with objects of the respective TestImpl<IntTest>, TestImpl<StringTest>, and so on. To avoid object slicing you need reference or pointer semantics, that is std::vector<std::unique_ptr<Test> > for example.
for (auto it = list.begin(); it != list.end(); ++it) {
(*it)->operate();
}

Best way to construct a string from components, iostream style

In many places in my code I need to construct understandable error messages, but creating string streams all the time is tedious, especially when you have to create a string in an constructor's initialisation list. If this could be done with a simple function it would make the code significantly more readable.
Given one of many example use cases below, what would be an elegant way of implementing the below createString function?
struct Base {
std::string msg;
Base(const std::string& msg) : msg(msg) { }
};
struct Derived: public Base {
Derived(int value)
// Parent constructor requires a string so we have to create it inline
: Base(createString("This is class " << value))
{ }
};
int main(void)
{
int i = 5; // some number obtained at runtime
Derived d(i);
std::cout << d.msg << "\n";
return 0;
}
So far I have come up with this C++11 version, but it suffers from a few drawbacks (requires preprocessor macro, sometimes strings have to be enclosed in std::string(), etc.) so I'm wondering whether anyone has come up with a better alternative?
#include <sstream>
#define createString(a) \
(static_cast<const std::ostringstream&>(std::ostringstream() << a).str())
Provide a wrapper around std::stringstream and have it be implicitly convertible to std::string. It changes the syntax a little bit:
class WrapSStream
{
public:
template <typename T>
WrapSStream& operator<<(const T& val)
{
ss << val;
return *this;
}
operator string(){return ss.str();}
private:
stringstream ss;
};
struct Base {
string msg;
Base(const string& msg) : msg(msg) { }
};
struct Derived: public Base {
Derived(int value)
// Parent constructor requires a string so we have to create it inline
: Base(WrapSStream() << "This is class " << value)
{ }
};
int main(void)
{
int i = 5; // some number obtained at runtime
Derived d(i);
cout << d.msg << "\n";
return 0;
}
Outputs This is class 5.
Live demo