Kno*_*abe 10 c++ templates c++11
是否有一种简单的方法可以强制编译器向我显示模板参数的推导类型?例如,给定
template<typename T>
void f(T&& parameter);
const volatile int * const pInt = nullptr;
f(pInt);
Run Code Online (Sandbox Code Playgroud)
我可能想看看T在调用中推断出什么类型f.(我想是的const volatile int *&,但我不确定.)或者给予
template<typename T>
void f(T parameter);
int numbers[] = { 5, 4, 3, 2, 1 };
f(numbers);
Run Code Online (Sandbox Code Playgroud)
我可能想看看我的猜测,T推断为int*在该呼叫f是正确的.
如果有第三方库解决方案(例如,来自Boost),我有兴趣了解它,但我也想知道是否有一种简单的方法可以强制进行包含推导类型的编译诊断.
How*_*ant 12
链接时解决方案:
在我的平台(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)
Run Code Online (Sandbox Code Playgroud)
不可否认,我得到了"三重参考",它应该被解释为左值参考(由于参考折叠),并且是一个解码错误(也许我可以解决这个问题).
运行时解决方案:
我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;
}
Run Code Online (Sandbox Code Playgroud)
我可以像以下一样使用它:
#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);
}
Run Code Online (Sandbox Code Playgroud)
对我来说打印出来:
PVKi const&
Run Code Online (Sandbox Code Playgroud)
这不是非常友好的输出.你的经历可能会更好.我的平台ABI基于Itanium ABI.这个ABI包括这个功能:
namespace abi
{
extern "C"
char*
__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status);
}
Run Code Online (Sandbox Code Playgroud)
我可以使用它来将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;
}
Run Code Online (Sandbox Code Playgroud)
现在以前main()打印出来:
int const volatile* const&
Run Code Online (Sandbox Code Playgroud)
我尝试了以下g ++ 4.7.2和clang ++ 3.4(trunk 184647); 他们都给
编译时错误,错误消息包含推断类型.
我无法访问MSVC 12,请检查发生的情况并提供反馈.
#include <string>
template <typename T>
struct deduced_type;
template<typename T>
void f(T&& ) {
deduced_type<T>::show;
}
int main() {
f(std::string()); // rvalue string
std::string lvalue;
f(lvalue);
const volatile int * const pInt = nullptr;
f(pInt);
}
Run Code Online (Sandbox Code Playgroud)
错误消息:g ++ 4.7.2
错误:deduced_type<std::basic_string<char> >嵌套名称说明符中使用的
不完整类型
错误:嵌套名称说明符中使用的不完整类型错误:嵌套名称说明符中使用的 不完整类型deduced_type<std::basic_string<char>&>deduced_type<const volatile int* const&>
和clang ++
错误:未定义模板的deduced_type<std::basic_string<char> >
隐式实例化deduced_type<std::basic_string<char> &>
错误:未定义模板的隐式实例化错误:未定义模板的隐式实例化deduced_type<const volatile int *const &>
例如,note/info消息还包含f两个编译器的类型
在实例化 void f(T&&) [with T = std::basic_string<char>]
这很丑,但很有效.
让编译器向您显示变量的类型(也许以一种迂回的方式);
T parameter;
....
void f(int x);
...
f(parameter);
Run Code Online (Sandbox Code Playgroud)
编译器应该抱怨“T”无法转换为 int,假设它实际上不能。