0

I'm making a simple Error class that should be thrown using throw statement, logged or written in console. The basic idea of the usage is:

//const char* filename is function argument
if(!file_exists(filename))
  throw Error(line, file, severity)<<"Invalid argument: the file does not exist: "<<filename;

I originally wanted to extend stringstream, but my searches indicate that it's impossible to extend on streams.

I'd really like to make the error class as convenient as you can see above, which means able to "eat" various types and append them to internal error message.

Community
  • 1
  • 1
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • An adapter to std::cerr? – Alexander V Dec 08 '14 at 23:30
  • `std::cerr` is just an **instance of** `std::ostream`, such as `std::cout`. It's an instance, not a **class** / **type**. Anyway, I want to store the input, not print it! – Tomáš Zato Dec 08 '14 at 23:32
  • Sorry for so much of bold font, but today I'm gettin' real tired of people who don't read questions/answers thoroughly. – Tomáš Zato Dec 08 '14 at 23:36
  • Is there anything that prevents you from overloading an operator<<(Error&, const std::string&)? I'd say that this should just work. – bialpio Dec 08 '14 at 23:39
  • @bialpio Nothing. But then I'd have to overload it for every type supported by `stringstream`. – Tomáš Zato Dec 08 '14 at 23:40
  • 1
    Then make the second parameter templated? – wakjah Dec 08 '14 at 23:42
  • @wakjah And what if the `stringstream` doesn't support value in template? It will then throw confusing errors. – Tomáš Zato Dec 08 '14 at 23:53
  • It is absolutely possible to extend streams. You are misunderstanding the Q&A you've linked to. Please read it again or refer to the documentation before you make such misinformed assumptions. – Captain Obvlious Dec 09 '14 at 00:38
  • @CaptainObvlious I don't think it's essentially wrong to do incorrect assuptions about something *when asking question*. In fact, I'm asking here because I was *doing something wrong*, right? Blaming question authors for being misinformed is dumbest thing of the day. – Tomáš Zato Dec 09 '14 at 00:41

1 Answers1

2

So actually it's not so hard. You can't inherit from stringstream directly - or I just didn't find out how. You'll soon drown in std template system...

template<class _Elem,
class _Traits,
class _Alloc>
// ... mom help me!

But, you can make a template:

template <class T>
Error& Error::operator<<(T const& value) {
    //private std::stringstream message
    message<<value;
    //You can also trigger code for every call - neat, ain't it? 
}

You'll be adding all values from this method to private variable within the class:

class Error
{
public:
    Error(int, const char*, int);
    ~Error(void);
    std::string file;
    unsigned int line;
    //Returns message.str()
    std::string what();
    //Calls message.operator<<()
    template <class T>
    Error& operator<< (T const& rhs);

private: 
    std::stringstream message;

};

There's still something I'm missing - how to distinguish between types supported by stringstream and others and throw error on the line of call, rather than in Error class. Also I'd like to write own handlers for unsupported types.

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • What do you mean? This won't compile if `T` doesn't support `operator<<` for `ostream`s, and all you need to do to support unsupported types is just that: provide an overload of the appropriate operator for your type and `ostream`. – wakjah Dec 08 '14 at 23:55
  • @wakjah It's just that it won't compile and will act like the error was in `Error.cpp` - not in the caller code. As of other overloads, I'll need to look up how templates work... – Tomáš Zato Dec 09 '14 at 00:05
  • 1
    Yes, template errors take a bit of getting used to. But you should just let the compiler do its job and emit the error. The alternative would be to implement a SFINAE check and use `static_assert` (e.g., see [this thread](http://stackoverflow.com/questions/5768511/using-sfinae-to-check-for-global-operator)), but it's very difficult to get a solution that covers all cases, so if I were you I'd just let the compiler do its job, which will cover all cases. Or wait for concepts to be implemented in your favourite environment :) – wakjah Dec 09 '14 at 00:13
  • 2
    `You can't inherit from stringstream directly` Sure you can, the issue is that streams can't be copied so you can't throw one. – user657267 Dec 09 '14 at 00:18