如何查看为模板类型参数推导出的类型? [英] How can I see the type deduced for a template type parameter?
问题描述
是否有一种简单的方法可以强制编译器向我显示为模板参数推导出的类型?例如,给定
Is there an easy way to force compilers to show me the type deduced for a template parameter? For example, given
template<typename T>
void f(T&& parameter);
const volatile int * const pInt = nullptr;
f(pInt);
我可能想看看在调用 f
时为 T
推导出什么类型.(我认为它是 const volatile int *&
,但我不确定.)或者给出
I might want to see what type is deduced for T
in the call to f
. (I think it's const volatile int *&
, but I'm not sure.) Or given
template<typename T>
void f(T parameter);
int numbers[] = { 5, 4, 3, 2, 1 };
f(numbers);
我可能想知道我在对 f
的调用中将 T
推导出为 int*
的猜测是否正确.
I might want to find out if my guess that T
is deduced to be int*
in the call to f
is correct.
如果有第三方库解决方案(例如,来自 Boost),我很想知道它,但我也想知道是否有一种简单的方法来强制编译诊断,其中包括推导类型.
If there's a third-party library solution (e.g., from Boost), I'd be interested to know about it, but I'd also like to know if there's an easy way to force a compilation diagnostic that would include the deduced type.
推荐答案
链接时间解决方案:
在我的平台 (OS X) 上,我可以通过简单地制作一个完整的短程序,减去我好奇的函数的定义,让链接器给我这些信息:
On my platform (OS X), I can get the linker to give me this information by simply making a short program that is complete, minus the definition of the function I'm curious about:
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)
诚然,我得到了三重引用",它应该被解释为左值引用(由于引用折叠),并且是一个 demanling 错误(也许我可以解决这个问题).
Admittedly I get the "triple reference", which should be interpreted as an lvalue reference (due to reference collapsing), and is a demangling bug (perhaps I can get that fixed).
运行时解决方案:
我保留了一个 type_name<T>()
函数来处理这种类型的事情.完全便携的一个是可能的,但对我来说是次优的.这是:
I keep a type_name<T>()
function handy for this type of thing. A completely portable one is possible, but sub-optimal for me. Here it is:
#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 基于 Itanium ABI.而这个 ABI 包括这个功能:
That's not terribly friendly output. Your experience may be better. My platform ABI is based on the Itanium ABI. And this ABI includes this function:
namespace abi
{
extern "C"
char*
__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status);
}
我可以使用它来将 C++ 符号分解为人类可读的形式.更新后的 type_name
可以利用这一点:
I can use this to demangle C++ symbols into a human readable form. An updated type_name<T>()
to take advantage of this is:
#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()
打印出来了:
And now the previous main()
prints out:
int const volatile* const&
这篇关于如何查看为模板类型参数推导出的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!