Home > Enterprise >  how to print template typename in c ? [duplicate]
how to print template typename in c ? [duplicate]

Time:10-06

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...

CodePudding user response:

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.

CodePudding user response:

First of all you should flip template arguments. Source can be autodeduce Target is not, so it should come first.

Second problem is that string literals can't be added like that. To build complex strings in C use std::ostringstream.

To get type information you can use typeid and since it is mangle and you already use boost you can use boost to print nice type human readable description of type by demagle that names.

Last thing: direct use of std::runtime_error is a bit lazy behavior, it is 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

  • Related