链接时间解决方案:
在我的平台(OS X)上,我可以通过简单地制作一个完整的短程序(减去我感兴趣的函数的定义)来让链接器为我提供此信息:
template<typename T>
void f(T&& parameter); // purposefully not defined
int
main()
{
const volatile int * const pInt = nullptr;
f(pInt);
}
Undefined symbols for architecture x86_64:
"void f<int const volatile* const&>(int const volatile* const&&&)", referenced from:
_main in test-9ncEvm.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
不可否认,我得到了“三重引用”,它应该被解释为左值引用(由于引用崩溃),并且是一个分解错误(也许我可以修复它)。
运行时解决方案:
我保留一个type_name<T>()
对于此类事情来说功能很方便。完全便携式的是可能的,但对我来说不是最佳的。这里是:
#include <type_traits>
#include <typeinfo>
#include <string>
template <typename T>
std::string
type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::string r = 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;
}
我可以这样使用它:
#include <iostream>
template<typename T>
void f(T&& parameter)
{
std::cout << type_name<T>() << '\n';
}
int
main()
{
const volatile int * const pInt = nullptr;
f(pInt);
}
对我来说打印出:
PVKi const&
这不是非常友好的输出。您的体验可能会更好。我的平台 ABI 基于安腾ABI http://mentorembedded.github.io/cxx-abi/。这个ABI包括这个函数:
namespace abi
{
extern "C"
char*
__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status);
}
我可以用它来将 C++ 符号分解为人类可读的形式。更新了type_name<T>()
利用这一点的方法是:
#include <type_traits>
#include <typeinfo>
#include <string>
#include <memory>
#include <cstdlib>
#include <cxxabi.h>
template <typename T>
std::string
type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void(*)(void*)> own
(
abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr),
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;
}
而现在之前的main()
打印出:
int const volatile* const&