Q:

Is it a good practice to parameterize error message in exception constructor?

I want to throw a exception with more detailed information about what input/result caused the problem. Then I can record helpful error message into log while I catch these exceptions. I am working on VS2012, which has not implemented parameter pack. So currently I use vsprintf to merge the variable length arguments into string.

Is it a good practice to use such printf-like functions at error handling stage?
Or it is just no need to carry such detail information in exception?

Exception 
class VargException : std::exception
{public:
    VargException (const char* fmt, ...)
    {
        va_list vargs;
        va_start(vargs, fmt);
        char buf[260] = {};
        vsprintf_s(buf, fmt, args);
        va_end(vargs);
        msgBuilt_ = tryAssign(msg_, buf);
    }
    const char* what() const { 
        return msgBuilt_? msg_.c_str(): "Error message failed to build"; 
    }
    std::string msg_;
    bool msgBuilt_;

    // Updated: Avoid dynamic std::string throw exception
    bool tryAssign(std::string& msg, const char* buf) throw()
    {
        try{ msg = buf; return true;} 
        catch (...) { return false; }
    }
};

Client code
void func(int key, int len) {
    try {
        if(notExists(key)) { throw VargException("%d key does not exist", key); }
        if(outOfRange(len)) { throw VargException("length %d is out of range.", len); }
        HRESULT hr = processSomething();
        if(FAILED(hr)) { throw VargException("FAILED to processingSomething. hr: 0x%08X", hr); }
    } catch (VargException& e) {
        std::cerr << e.what() << "\n";
    }
}

A:

In an exception creation/handling code, you should be more paranoid about exceptions.
Constructing a std::string can throw.
I would add that paranoia, and otherwise accept the design.  Look up some tokens to detect 2013 mode and issue warnings/deprecation messages.

