2

I am writing a wrapper for boost numeric_cast with the wrapper function something like:

#include <boost/numeric/conversion/cast.hpp> #include <stdexcept> template <typename Source, typename Target> Target numeric_cast(Source src) { try { // calling boost numeric_cast here } catch(boost::numeric::bad_numeric_cast& e) { throw std::runtime_error("numeric_cast failed, fromType: " + Source + " toType: " + Target); } } 

I am having this error:

error: expected primary-expression before ‘(’ token throw std::runtime_error("numeric_cast failed ... ^ 

I think the error is asking to handle Source and Target in the error message. So is there a way to print template typename? I am a beginner in c++, so it maybe a silly question...

4
  • what is Source and Target ? You seem to confuse types with values. What is the expected message for the exception? Commented Oct 6, 2021 at 9:28
  • I want it to be something like: numeric_cast failed, fromType: int, toType: short Commented Oct 6, 2021 at 9:30
  • Target must be first since Source will be auto deduced. Commented Oct 6, 2021 at 9:33
  • 1
    stackoverflow.com/questions/281818/… Commented Oct 6, 2021 at 9:40

2 Answers 2

2

You can use typeid(T).name() to get the raw string of the template parameter:

#include <boost/numeric/conversion/cast.hpp> #include <stdexcept> #include <typeinfo> template <typename Source, typename Target> Target numeric_cast(Source src) { try { // calling boost numeric_cast here } catch(boost::numeric::bad_numeric_cast& e) { throw (std::string("numeric_cast failed, fromType: ") + typeid(Source).name() + " toType: " + typeid(Target).name()); } } 

Demo.

Please note that the string literal "numeric_cast failed, fromType:" should be std::string type to support '+' operator.

Sign up to request clarification or add additional context in comments.

4 Comments

Notice that typeid(T).name() returns implementation specific value. you might got "i" or "int" depending of compiler for example.
Yes, but I think using typeid is enough to express type information in this case.
@Jarod42 yes, it is showing i for int, s for short etc for my case(linux), is there a way to handle this?
1

First of all you should flip template arguments. Source can be auto-deduced on other hand Target can't. So Target must be explicitly provided and should come first in template parameter list, so Source could be deduced anyway.

Second problem is that string literals can't be added like that (this comes from C). To build complex strings in C++ use std::ostringstream.

To get type name information you can use typeid. Since this name is mangled and you already use boost, you can demagle that names using boost and get nice human readable type name.

Last thing: direct use of std::runtime_error is manifestation of lazy developer. It is a good practice to introduce own exception class for such scenarios.

#include <iostream> #include <sstream> #include <boost/numeric/conversion/cast.hpp> #include <boost/core/demangle.hpp> #include <typeinfo> #include <stdexcept> template<typename T> std::string typeName() { return boost::core::demangle(typeid(T).name()); } // this is used to bind all exceptions related to local library class MyLibExceptions : public std::exception {}; class BadNumericCast : public MyLibExceptions { public: template<typename Target, typename Source> BadNumericCast(Source arg, Target, const char *extra) { std::ostringstream desc; desc << extra << " from type: '" << typeName<Source>() << "' with value: " << arg << " to type: '" << typeName<Target>() << '\''; mDesc = desc.str(); } const char* what() const noexcept override { return mDesc.c_str(); } private: std::string mDesc; }; template <typename Target, typename Source> Target numeric_cast(Source arg) { try { return boost::numeric::converter<Target, Source>::convert(arg); } catch(boost::numeric::bad_numeric_cast& e) { throw BadNumericCast{arg, Target{}, e.what()}; } } 

Live demo

2 Comments

could we skip the Target parameter from the BadNumericCast class constructor?
@DonBaka stackoverflow.com/a/2861859/1387438 (second answer has nice workaround)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.