Click here to Skip to main content
14,937,188 members
Articles / Programming Languages / C++
Tip/Trick
Posted 4 May 2020

Tagged as

Stats

3.5K views
4 bookmarked

Generating a String of a Method Name and of its Arguments in C++

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
4 May 2020CPOL
Method utilizing variadic arguments and macros
A method utilizing variadic arguments and variadic macros is presented which permits the simple generation of a string of any method name and of its arguments from within that method.

Introduction

If you need to obtain a string of a method name and of its arguments perhaps when throwing std::invalid_argument, variadic arguments and variadic macros make it easy to do so. The procedure presented here requires arguments of class type accept operator << shown below.

C++
operator << (basic_ostream<char>&, const class type&)

The code which generates the string of the class and method name and its argument type names and their values is shown below:

C++
#include <sstream>

using namespace std;

template <typename First> string args_to_string(const First& first)
{
	char space = ' ';
	ostringstream oss;
	oss << typeid(first).name() << space << first;
	return oss.str();
}
template <typename First, typename... Rest> _
    string args_to_string(const First& first, const Rest&... rest)
{
	char space = ' ';
	char comma = ',';
	ostringstream oss;
	oss << typeid(first).name() << space << first;
	oss << comma << space;
	oss << args_to_string(rest...); // recursive call using pack expansion syntax
	return oss.str();
}

#define CLASSSTRING string(typeid(*this).name())
#define CLASSMETHODSTRING CLASSSTRING + string("::") + string(__func__)
#define ARGSSTRING(...) string("(") + args_to_string(__VA_ARGS__) + string(")")
#define CLASSMETHODARGSSTRING(...) CLASSMETHODSTRING + ARGSSTRING(__VA_ARGS__)

Only...

C++
CLASSMETHODARGSSTRING(arg1, etc.)

...needs to be inserted into your code as shown below:

C++
#include <above code in manner you prefer>
#include <iostream>
#include <stdexcept>

template<class T>
class cgoobar {
	T m_x;
public:
	cgoobar() : m_x(0) {}
	template<typename charT>
	friend
		basic_ostream<charT>& operator << (basic_ostream<charT>& os, const cgoobar& gb)
	{
		os << gb.m_x;
		return os;
	}
};

template<class T>
class cfoobar
{
public:
	template<class T, class U>
	void foobar(T x, U y) { if (!x) throw invalid_argument(CLASSMETHODARGSSTRING(x, y)); }
};

int main()
{
	cfoobar<int> fb;
	cgoobar<double> gb;
	try { fb.foobar(0, gb); }
	catch (const invalid_argument& ex) { cout << ex.what(); }
}

The output of the code demonstrating its correctness as it was thrown by the indicated method with the indicated arguments is:

C++
class cfoobar<int>::foobar(int 0, class cgoobar<double> 0)

History

  • 4th May, 2020: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

PaltryProgrammer
United States United States
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --