I have three files:
main.cpp
MyClass.cpp
MyClass.hpp
I have a library header file, "testLib.hpp", that I want to include in MyClass.hpp so that I can have one of testLib's objects be a class attribute.
I include MyClass.hpp in MyClass.cpp and in main.cpp. When attempting to compile the project, I get the following errors
MyClass.cpp multiple definition of 'testLib::testLib::function1()
obj/Release/main.o:main.cpp first defined here
MyClass.cpp multiple definition of 'testLib::testLib::function2()
obj/Release/main.o:main.cpp first defined here
and so on.
Both main.cpp and MyClass.cpp include MyClass.hpp (which includes testLib.hpp). Judging by the error, it looks like MyClass.cpp is attempting to include the library functions after they've already been included by main.cpp. However, I have include guards present in MyClass.hpp so I don't understand how it's trying to include MyClass.hpp twice.
Here's the code:
MyClass.hpp
#ifndef THIS_HEADER_H
#define THIS_HEADER_H
#include <stdint.h>
#include <iostream>
#include "testLib/testLib.hpp"
class MyClass
{
public:
void test();
int foo;
private:
uint32_t bar;
//I want to include an object from the library as part of this class
//TestLib::Device device;
};
#endif
MyClass.cpp
#include <stdio.h>
#include "MyClass.hpp"
void MyClass::test()
{
}
main.cpp
#include <iostream>
#include "MyClass.hpp"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
return 0;
}
Any help would be greatly appreciated!
EDIT
I tried to hide the actual filenames to make the question more general and clear, but it seems like the problem might be resulting from 'testLib.hpp', which I did not write. That file is actually the following "sweep.hpp" file. I got the 'multiple definition of/first defined here' errors for each of the public functions in this file:
sweep.hpp
#ifndef SWEEP_DC649F4E94D3_HPP
#define SWEEP_DC649F4E94D3_HPP
/*
* C++ Wrapper around the low-level primitives.
* Automatically handles resource management.
*
* sweep::sweep - device to interact with
* sweep::scan - a full scan returned by the device
* sweep::sample - a single sample in a full scan
*
* On error sweep::device_error gets thrown.
*/
#include <cstdint>
#include <memory>
#include <stdexcept>
#include <vector>
#include <sweep/sweep.h>
namespace sweep {
// Error reporting
struct device_error final : std::runtime_error {
using base = std::runtime_error;
using base::base;
};
// Interface
struct sample {
const std::int32_t angle;
const std::int32_t distance;
const std::int32_t signal_strength;
};
struct scan {
std::vector<sample> samples;
};
class sweep {
public:
sweep(const char* port);
sweep(const char* port, std::int32_t bitrate);
void start_scanning();
void stop_scanning();
bool get_motor_ready();
std::int32_t get_motor_speed();
void set_motor_speed(std::int32_t speed);
std::int32_t get_sample_rate();
void set_sample_rate(std::int32_t speed);
scan get_scan();
void reset();
private:
std::unique_ptr<::sweep_device, decltype(&::sweep_device_destruct)> device;
};
// Implementation
namespace detail {
struct error_to_exception {
operator ::sweep_error_s*() { return &error; }
~error_to_exception() noexcept(false) {
if (error) {
device_error e{::sweep_error_message(error)};
::sweep_error_destruct(error);
throw e;
}
}
::sweep_error_s error = nullptr;
};
}
sweep::sweep(const char* port)
: device{::sweep_device_construct_simple(port, detail::error_to_exception{}), &::sweep_device_destruct} {}
sweep::sweep(const char* port, std::int32_t bitrate)
: device{::sweep_device_construct(port, bitrate, detail::error_to_exception{}), &::sweep_device_destruct} {}
void sweep::start_scanning() { ::sweep_device_start_scanning(device.get(), detail::error_to_exception{}); }
void sweep::stop_scanning() { ::sweep_device_stop_scanning(device.get(), detail::error_to_exception{}); }
bool sweep::get_motor_ready() { return ::sweep_device_get_motor_ready(device.get(), detail::error_to_exception{}); }
std::int32_t sweep::get_motor_speed() { return ::sweep_device_get_motor_speed(device.get(), detail::error_to_exception{}); }
void sweep::set_motor_speed(std::int32_t speed) {
::sweep_device_set_motor_speed(device.get(), speed, detail::error_to_exception{});
}
std::int32_t sweep::get_sample_rate() { return ::sweep_device_get_sample_rate(device.get(), detail::error_to_exception{}); }
void sweep::set_sample_rate(std::int32_t rate) {
::sweep_device_set_sample_rate(device.get(), rate, detail::error_to_exception{});
}
scan sweep::get_scan() {
using scan_owner = std::unique_ptr<::sweep_scan, decltype(&::sweep_scan_destruct)>;
scan_owner releasing_scan{::sweep_device_get_scan(device.get(), detail::error_to_exception{}), &::sweep_scan_destruct};
auto num_samples = ::sweep_scan_get_number_of_samples(releasing_scan.get());
scan result;
result.samples.reserve(num_samples);
for (std::int32_t n = 0; n < num_samples; ++n) {
auto angle = ::sweep_scan_get_angle(releasing_scan.get(), n);
auto distance = ::sweep_scan_get_distance(releasing_scan.get(), n);
auto signal = ::sweep_scan_get_signal_strength(releasing_scan.get(), n);
result.samples.push_back(sample{angle, distance, signal});
}
return result;
}
void sweep::reset() { ::sweep_device_reset(device.get(), detail::error_to_exception{}); }
} // ns
#endif
A simplified version of your problem:
buggy.hpp
int function() { return 0; }
main.cpp
#include "buggy.hpp"
int main() { return 0; }
other.cpp
#include "buggy.hpp"
The problem is that buggy.hpp is defining function, not just declaring. Once the header inclusion is expanded, that means function is declared in both main.cpp and other.cpp - and that is not allowed.
The fix is to declare function as inline which allows the function to be declared in multiple translation units.
inline int function() { return 0; }
In fact, allowing multiple definitions is the only meaning of inline to the C++ standard. Compilers may treat it as a hint that the function body may be expanded inline. Good ones won't; they are better at making that sort of decision that programmers).
This may be a really easy question but... here it goes. (Thanks in advance!)
I am simplifying the code so it is understandable. I want to use a variable calculated inside another class without running everything again.
source.ccp
#include <iostream>
#include "begin.h"
#include "calculation.h"
using namespace std;
int main()
{
beginclass BEGINOBJECT;
BEGINOBJECT.collectdata();
cout << "class " << BEGINOBJECT.test;
calculationclass SHOWRESULT;
SHOWRESULT.multiply();
system("pause");
exit(1);
}
begin.h
#include <iostream>
using namespace std;
#ifndef BEGIN_H
#define BEGIN_H
class beginclass
{
public:
void collectdata();
int test;
};
#endif
begin.cpp
#include <iostream>
#include "begin.h"
void beginclass::collectdata()
{
test = 6;
}
calculation.h
#include <iostream>
#include "begin.h"
#ifndef CALCULATION_H
#define CALCULATION_H
class calculationclass
{
public:
void multiply();
};
#endif
calculation.cpp
#include <iostream>
#include "begin.h"
#include "calculation.h"
void calculationclass::multiply()
{
beginclass BEGINOBJECT;
// BEGINOBJECT.collectdata(); // If I uncomment this it works...
int abc = BEGINOBJECT.test * 2;
cout << "\n" << abc << endl;
}
Simply define member function multiply as
void calculationclass::multiply( const beginclass &BEGINOBJECT ) const
{
int abc = BEGINOBJECT.test * 2;
cout << "\n" << abc << endl;
}
And call it as
int main()
{
beginclass BEGINOBJECT;
BEGINOBJECT.collectdata();
cout << "class " << BEGINOBJECT.test;
calculationclass SHOWRESULT;
SHOWRESULT.multiply( BEGINOBJECT );
system("pause");
exit(1);
}
In your code beginclass has no explicit constructor, hence the implicitly defined default constructor will be used, which default constructs all members. Hence, after construction beginclass::test is either 0 or uninitiliased.
What you appear to be wanting is to avoid to call beginclass::collectdata() more than once. For this you would want to set a flag that remembers if beginclass::collectdata() has been called. The member function which returns the data then first checks this flags and, if the flag was not set, calls beginclass::collectdata() first. See also the answer by CashCow.
It looks like you are looking for some kind of lazy evaluation / caching technique whereby a value is calculated the first time it is requested then stored to return it subsequently without having to reevaluate.
In a multi-threaded environment the way to achieve this (using the new standard thread library) is by using std::call_once
If you are in a single-threaded environment, and you just want to get a value out of a class, use a getter for that value. If it isn't calculated in a "lazy" fashion, i.e. the class calculates it instantly, you can put that logic in the class's constructor.
For a "calc_once" example:
class calculation_class
{
std::once_flag flag;
double value;
void do_multiply();
double multiply();
public:
double multiply()
{
std::call_once( flag, do_multiply, this );
return value;
}
};
If you want multiply to be const, you'll need to make do_multiply also const and value and flag mutable.
I'm getting a runtime error ("memory can't be written") that, after inspection through the debugger, leads to the warning in the tittle.
The headers are the following:
componente.h:
#ifndef COMPONENTE_H
#define COMPONENTE_H
using namespace std;
class componente
{
int num_piezas;
int codigo;
char* proovedor;
public:
componente();
componente(int a, int b, const char* c);
virtual ~componente();
virtual void print();
};
#endif // COMPONENTE_H
complement.h implementation
#include "Componente.h"
#include <string.h>
#include <iostream>
componente::componente()
{
num_piezas = 0;
codigo = 0;
strcpy(proovedor, "");
//ctor
}
componente::componente(int a = 0, int b = 0, const char* c = "")
{
num_piezas = a;
codigo = b;
strcpy(proovedor, "");
}
componente::~componente()
{
delete proovedor;//dtor
}
void componente::print()
{
cout << "Proovedor: " << proovedor << endl;
cout << "Piezas: " << num_piezas << endl;
cout << "Codigo: " << codigo << endl;
}
teclado.h
#ifndef TECLADO_H
#define TECLADO_H
#include "Componente.h"
class teclado : public componente
{
int teclas;
public:
teclado();
teclado(int a, int b, int c, char* d);
virtual ~teclado();
void print();
};
#endif // TECLADO_H
teclado.h implementation
#include "teclado.h"
#include <iostream>
teclado::teclado() : componente()
{
teclas = 0;//ctor
}
teclado::~teclado()
{
teclas = 0;//dtor
}
teclado::teclado(int a = 0, int b = 0, int c = 0, char* d = "") : componente(a,b,d)
{
teclas = c;
}
void teclado::print()
{
cout << "Teclas: " << teclas << endl;
}
The main method where I get the runtime error is the following:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
componente a; // here I have the breakpoint where I check this warning
a.print();
return 0;
}
BUT, if instead of creating an "componente" object, I create a "teclado" object, I don't get the runtime error. I STILL get the warning during debugging, but the program behaves as expected:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
teclado a;
a.print();
return 0;
}
This returns "Teclas = 0" plus the "Press any key..." thing.
Do you have any idea why the linker is having troube with this? It doesn't show up when I invoke the virtual function, but before, during construction.
Two errors that I can see:
strcpy(proovedor, ""); // No memory has been allocated to `proovedor` and
// it is uninitialised.
As it is uninitialised this could be overwriting anywhere in the process memory, so could be corrupting the virtual table.
You could change this to (in both constructors):
proovedor = strdup("");
Destructor uses incorrect delete on proovedor:
delete proovedor; // should be delete[] proovedor
As this is C++ you should considering using std::string instead of char*.
If you do not change to std::string then you need to either:
Implement a copy constructor and assignment operator as the default versions are incorrect if you have a member variable that is dynamically allocated, or
Make the copy constructor and assignment operator private to make it impossible for them to be used.
Another source of this same message is that gdb can get confused by not-yet-initialized variables. (This answers the question title, but not the OP's question, since a web search led me here looking for an answer.)
Naturally, you shouldn't have uninitialized variables, but in my case gdb attempts to show function local variables even before they are declared/initialized.
Today I'm stepping through another developer's gtest case and this message was getting dumped to output every time the debugger stopped. In this case, the variable in question was declared on ~line 245, but the function started on ~line 202. Every time I stopped the debugger between these lines, I received the message.
I worked around the issue by moving the variable declaration to the top of the function.
For reference, I am testing with gdb version 7.11.1 in QtCreator 4.1.0 and I compiled with g++ version 5.4.1
I'm currently working on some logging code that supposed to - among other things - print information about the calling function. This should be relatively easy, standard C++ has a type_info class. This contains the name of the typeid'd class/function/etc. but it's mangled. It's not very useful. I.e. typeid(std::vector<int>).name() returns St6vectorIiSaIiEE.
Is there a way to produce something useful from this? Like std::vector<int> for the above example. If it only works for non-template classes, that's fine too.
The solution should work for gcc, but it would be better if I could port it. It's for logging so it's not so important that it can't be turned off, but it should be helpful for debugging.
Given the attention this question / answer receives, and the valuable feedback from GManNickG, I have cleaned up the code a little bit. Two versions are given: one with C++11 features and another one with only C++98 features.
In file type.hpp
#ifndef TYPE_HPP
#define TYPE_HPP
#include <string>
#include <typeinfo>
std::string demangle(const char* name);
template <class T>
std::string type(const T& t) {
return demangle(typeid(t).name());
}
#endif
In file type.cpp (requires C++11)
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
// enable c++11 by passing the flag -std=c++11 to g++
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif
Usage:
#include <iostream>
#include "type.hpp"
struct Base { virtual ~Base() {} };
struct Derived : public Base { };
int main() {
Base* ptr_base = new Derived(); // Please use smart pointers in YOUR code!
std::cout << "Type of ptr_base: " << type(ptr_base) << std::endl;
std::cout << "Type of pointee: " << type(*ptr_base) << std::endl;
delete ptr_base;
}
It prints:
Type of ptr_base: Base*
Type of pointee: Derived
Tested with g++ 4.7.2, g++ 4.9.0 20140302 (experimental), clang++ 3.4 (trunk 184647), clang 3.5 (trunk 202594) on Linux 64 bit and g++ 4.7.2 (Mingw32, Win32 XP SP2).
If you cannot use C++11 features, here is how it can be done in C++98, the file type.cpp is now:
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
struct handle {
char* p;
handle(char* ptr) : p(ptr) { }
~handle() { std::free(p); }
};
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
handle result( abi::__cxa_demangle(name, NULL, NULL, &status) );
return (status==0) ? result.p : name ;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif
(Update from Sep 8, 2013)
The accepted answer (as of Sep 7, 2013), when the call to abi::__cxa_demangle() is successful, returns a pointer to a local, stack allocated array... ouch!
Also note that if you provide a buffer, abi::__cxa_demangle() assumes it to be allocated on the heap. Allocating the buffer on the stack is a bug (from the gnu doc): "If output_buffer is not long enough, it is expanded using realloc." Calling realloc() on a pointer to the stack... ouch! (See also Igor Skochinsky's kind comment.)
You can easily verify both of these bugs: just reduce the buffer size in the accepted answer (as of Sep 7, 2013) from 1024 to something smaller, for example 16, and give it something with a name not longer than 15 (so realloc() is not called). Still, depending on your system and the compiler optimizations, the output will be: garbage / nothing / program crash.
To verify the second bug: set the buffer size to 1 and call it with something whose name is longer than 1 character. When you run it, the program almost assuredly crashes as it attempts to call realloc() with a pointer to the stack.
(The old answer from Dec 27, 2010)
Important changes made to KeithB's code: the buffer has to be either allocated by malloc or specified as NULL. Do NOT allocate it on the stack.
It's wise to check that status as well.
I failed to find HAVE_CXA_DEMANGLE. I check __GNUG__ although that does not guarantee that the code will even compile. Anyone has a better idea?
#include <cxxabi.h>
const string demangle(const char* name) {
int status = -4;
char* res = abi::__cxa_demangle(name, NULL, NULL, &status);
const char* const demangled_name = (status==0)?res:name;
string ret_val(demangled_name);
free(res);
return ret_val;
}
Boost core contains a demangler. Checkout core/demangle.hpp:
#include <boost/core/demangle.hpp>
#include <typeinfo>
#include <iostream>
template<class T> struct X
{
};
int main()
{
char const * name = typeid( X<int> ).name();
std::cout << name << std::endl; // prints 1XIiE
std::cout << boost::core::demangle( name ) << std::endl; // prints X<int>
}
It's basically just a wrapper for abi::__cxa_demangle, as has been suggested previously.
If all we want is the unmangled type name for the purpose of logging, we can actually do this without using std::type_info or even RTTI at all.
A slightly portable solution that works for the big 3 main compiler front-ends (gcc, clang, and msvc) would be to use a function template and extract the type name from the function name.
gcc and clang both offer __PRETTY_FUNCTION__ which is the name of a current function or function template with all type-argument in the string. Similarly MSVC has __FUNCSIG__ which is equivalent. Each of these are formatted a little differently, for example, for a call of void foo<int>, the compilers will output something different:
gcc is formatted void foo() [with T = int; ]
clang is formatted void foo() [T = int]
msvc is formatted void foo<int>()
Knowing this, it's just a matter of parsing out a prefix and suffix and wrapping this into a function in order to extract out the type name.
We can even use c++17's std::string_view and extended constexpr to get string names at compile-time, just by parsing the name of a template function. This could also be done in any earlier C++ version, but this will still require some form of string parsing.
For example:
#include <string_view>
template <typename T>
constexpr auto get_type_name() -> std::string_view
{
#if defined(__clang__)
constexpr auto prefix = std::string_view{"[T = "};
constexpr auto suffix = "]";
constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
#elif defined(__GNUC__)
constexpr auto prefix = std::string_view{"with T = "};
constexpr auto suffix = "; ";
constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
#elif defined(_MSC_VER)
constexpr auto prefix = std::string_view{"get_type_name<"};
constexpr auto suffix = ">(void)";
constexpr auto function = std::string_view{__FUNCSIG__};
#else
# error Unsupported compiler
#endif
const auto start = function.find(prefix) + prefix.size();
const auto end = function.find(suffix);
const auto size = end - start;
return function.substr(start, size);
}
With this, you can call get_type_name<T>() to get a std::string_view at compile-time indicating the unmangled type name.
For example:
std::cout << get_type_name<std::string>() << std::endl;
on GCC will output:
std::__cxx11::basic_string<char>
and on clang will output:
std::basic_string<char>
Live Example
A similar augmentation to this approach which avoids a prefix and suffix is to assume that the function name is the same for all types, and search for a sentinel type to parse out the offset to the sentinel from each end. This ensures that the string searching only happens once, and the offset is assumed to find the string name each time. For example, using double as a simple sentinel:
template <typename T>
constexpr auto full_function_name() -> std::string_view
{
#if defined(__clang__) || defined(__GNUC__)
return std::string_view{__PRETTY_FUNCTION__};
#elif defined(_MSC_VER)
return std::string_view{__FUNCSIG__};
#else
# error Unsupported compiler
#endif
}
// Outside of the template so its computed once
struct type_name_info {
static constexpr auto sentinel_function = full_function_name<double>();
static constexpr auto prefix_offset = sentinel_function.find("double");
static constexpr auto suffix_offset = sentinel_function.size() - prefix_offset - /* strlen("double") */ 6;
};
template <typename T>
constexpr auto get_type_name() -> std::string_view
{
constexpr auto function = full_function_name<T>();
const auto start = type_name_info::prefix_offset;
const auto end = function.size() - type_name_info::suffix_offset;
const auto size = end - start;
return function.substr(start, size);
}
Live Example
This isn't portable to all compilers, but can be modified for any compiler that offers a __FUNCSIG__/__PRETTY_FUNCTION__ equivalent; it just requires a bit of parsing.
note: This hasn't been fully tested, so there may be some bugs; but the primary idea is to parse any output that contains the name in totality -- which is often a side-effect of __func__-like outputs on compilers.
This is what we use. HAVE_CXA_DEMANGLE is only set if available (recent versions of GCC only).
#ifdef HAVE_CXA_DEMANGLE
const char* demangle(const char* name)
{
char buf[1024];
unsigned int size=1024;
int status;
char* res = abi::__cxa_demangle (name,
buf,
&size,
&status);
return res;
}
#else
const char* demangle(const char* name)
{
return name;
}
#endif
Here, take a look at type_strings.hpp it contains a function that does what you want.
If you just look for a demangling tool, which you e.g. could use to mangle stuff shown in a log file, take a look at c++filt, which comes with binutils. It can demangle C++ and Java symbol names.
It's implementation defined, so it's not something that's going to be portable. In MSVC++, name() is the undecorated name, and you have to look at raw_name() to get the decorated one.
Just a stab in the dark here, but under gcc, you might want to look at demangle.h
I also found a macro called __PRETTY_FUNCTION__, which does the trick. It gives a pretty function name (figures :)). This is what I needed.
I.e. it gives me the following:
virtual bool mutex::do_unlock()
But I don't think it works on other compilers.
The accepted solution [1] works mostly well.
I found at least one case (and I wouldn't call it a corner case) where it does not report what I expected... with references.
For those cases, I found another solution, posted at the bottom.
Problematic case (using type as defined in [1]):
int i = 1;
cout << "Type of " << "i" << " is " << type(i) << endl;
int & ri = i;
cout << "Type of " << "ri" << " is " << type(ri) << endl;
produces
Type of i is int
Type of ri is int
Solution (using type_name<decltype(obj)>(), see code below):
cout << "Type of " << "i" << " is " << type_name<decltype(i)>() << endl;
cout << "Type of " << "ri" << " is " << type_name<decltype(ri)>() << endl;
produces
Type of i is int
Type of ri is int&
as desired (at least by me)
Code
.
It has to be in an included header, not in a separately compiled source, due to specialization issues. See undefined reference to template function for instance.
#ifndef _MSC_VER
# include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>
template <class T>
std::string
type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void(*)(void*)> own
(
#ifndef _MSC_VER
abi::__cxa_demangle(typeid(TR).name(), nullptr,
nullptr, nullptr),
#else
nullptr,
#endif
std::free
);
std::string r = own != nullptr ? own.get() : typeid(TR).name();
if (std::is_const<TR>::value)
r += " const";
if (std::is_volatile<TR>::value)
r += " volatile";
if (std::is_lvalue_reference<T>::value)
r += "&";
else if (std::is_rvalue_reference<T>::value)
r += "&&";
return r;
}
Not a complete solution, but you may want to look at what some of the standard (or widely supported) macro's define. It's common in logging code to see the use of the macros:
__FUNCTION__
__FILE__
__LINE__
e.g.:
log(__FILE__, __LINE__, __FUNCTION__, mymessage);
A slight variation on Ali's solution. If you want the code to still be very similar to
typeid(bla).name(),
writing this instead
Typeid(bla).name() (differing only in capital first letter)
then you may be interested in this:
In file type.hpp
#ifndef TYPE_HPP
#define TYPE_HPP
#include <string>
#include <typeinfo>
std::string demangle(const char* name);
/*
template <class T>
std::string type(const T& t) {
return demangle(typeid(t).name());
}
*/
class Typeid {
public:
template <class T>
Typeid(const T& t) : typ(typeid(t)) {}
std::string name() { return demangle(typ.name()); }
private:
const std::type_info& typ;
};
#endif
type.cpp stays same as in Ali's solution
Following Ali's solution, here is the C++11 templated alternative which worked best for my usage.
// type.h
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
template <typename T>
std::string demangle() {
int status = -4;
std::unique_ptr<char, void (*)(void*)> res{
abi::__cxa_demangle(typeid(T).name(), NULL, NULL, &status), std::free};
return (status == 0) ? res.get() : typeid(T).name();
}
Usage:
// main.cpp
#include <iostream>
namespace test {
struct SomeStruct {};
}
int main()
{
std::cout << demangle<double>() << std::endl;
std::cout << demangle<const int&>() << std::endl;
std::cout << demangle<test::SomeStruct>() << std::endl;
return 0;
}
Will print:
double
int
test::SomeStruct
Take a look at __cxa_demangle which you can find at cxxabi.h.
// KeithB's solution is good, but has one serious flaw in that unless buf is static
// it'll get trashed from the stack before it is returned in res - and will point who-knows-where
// Here's that problem fixed, but the code is still non-re-entrant and not thread-safe.
// Anyone care to improve it?
#include <cxxabi.h>
// todo: javadoc this properly
const char* demangle(const char* name)
{
static char buf[1024];
size_t size = sizeof(buf);
int status;
// todo:
char* res = abi::__cxa_demangle (name,
buf,
&size,
&status);
buf[sizeof(buf) - 1] = 0; // I'd hope __cxa_demangle does this when the name is huge, but just in case.
return res;
}
I've always wanted to use type_info, but I'm sure that the result of the name() member function is non-standard and won't necessarily return anything that can be converted to a meaningful result.
If you are sticking to one compiler, there maybe a compiler specific function that will do what you want. Check the documentation.
boost::typeindex provides something helpful.
#include <boost/type_index.hpp>
#include <iostream>
#include <vector>
class Widget {};
int main() {
using boost::typeindex::type_id_with_cvr;
const std::vector<Widget> vw;
std::cout << type_id_with_cvr<decltype(vw)>().pretty_name() << std::endl;
std::cout << type_id_with_cvr<decltype(vw[0])>().pretty_name() << std::endl;
return 0;
}
The output is
std::vector<Widget, std::allocator<Widget> > const
Widget const&
What is worthy of notice is that type_id_with_cvr preserves reference and c/v qualifiers, while typeid doesn't. See the following example:
#include <iostream>
#include <boost/type_index.hpp>
#include <typeindex>
#include <vector>
#include <typeinfo>
class Widget {};
template <typename T>
void f(const T ¶m) {
std::cout << typeid(param).name() << std::endl;
std::cout
<< boost::typeindex::type_id_with_cvr<decltype(param)>().pretty_name()
<< std::endl;
}
int main() {
const std::vector<Widget> vw(1);
f(&vw[0]);
return 0;
}
The output is
PK6Widget
Widget const* const&
Here, typeid produces PK6Widget, which means Pointer to Konst Widget. The number '6' is the length of the name 'Widget'. This is not the correct type of param, in which the reference and const qualifier are dropped.
The type_id_with_cvr actually uses the demangling functions in boost::core, as has been mentioned in this answer. To preserve the cv qualifiers or reference, it just defines an empty template named cvr_saver and then passes cvr_saver<type> to typeid.
Effective Modern C++ Item 4 talks about this.