如何检测表达式的类型?

3
有时候,代码中会出现复杂的表达式。例如,频繁使用Boost库就会导致这些表达式的出现。如果我想typedef这些表达式的类型,就需要编写它的类型。有没有一种方法可以在编译时(或运行时)知道这个类型?也许Boost提供了适当的功能。我想像这样使用它:
#pragma message (...expression...)

编辑:如果在编译时类型检测存在问题,则运行时类型检测也适用。例如,像下面这样的函数就很合适。

template <typename T> std::string detectExpressionType(T t);

2
c++11 添加了 decltype 关键字,但由于您标记了问题为 c++03... - galop1n
请大家不要再提decltype()了。这个问题标记为C++03,所以问题实际上是:我没有C++11的decltype,那么我如何在编译时检测表达式的类型? - Manu343726
@Manu343726 decltype至少是一个有用的搜索词,可以找到C++11之前非标准关键字和类似的笨拙技术,这些技术促成了decltype的标准化。 - Tony Delroy
2个回答

2

在C++03中,您可以使用模板参数推导:

template<typename T>
void foo(T x)
{
    // Now you have the type of the expression.
}

int main()
{
    foo(1.0f * 2.0f);
}

然而,你不能在#pragma message (...expression...)的情况下使用这个方法,因为#pragma是一个预处理器指令。你不能在预处理阶段使用任何类型信息。


一些库故意制造错误,以生成消息,他们发现这种错误在他们所针对的编译器上会出现问题类型的文档 - 例如,尝试将值转换为某个类型会产生“无法从类型XYZ转换为<whatever>”的消息。 这种方法不允许自定义消息,并且可能会令人困惑,但可以在前面加上一个#pragma message,以解释更多上下文信息... - Tony Delroy

1
如果你需要进行调试,就让它失败。如果运行时信息足够好,你可以解开类型的名称(下面是针对gcc的解析)。

#include <iostream>
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>

template <typename T> struct DebugType;
template <typename T>
inline void debug_type() {
    DebugType<T>();
}
template <typename T>
inline void debug_type(const T&) {
    DebugType<T>();
}

std::string demangle(const std::string& source_name)
{
    std::string result;
    size_t size = 4096;
    // __cxa_demangle may realloc()
    char* name = static_cast<char*>(malloc(size));
    try {
        int status;
        char* demangle = abi::__cxa_demangle(source_name.c_str(), name, &size, &status);
        if(demangle) result = demangle;
        else result = source_name;
    }
    catch(...) {}
    free(name);
    return result;
}

template <typename T>
inline void log_type() {
    std::clog << demangle(typeid(T).name()) << '\n';
}

template <typename T>
inline void log_type(const T&) {
    std::clog << demangle(typeid(T).name()) << '\n';
}

int main()  {
    // error: incomplete type ‘DebugType<int>’ used in nested name specifier
    // debug_type<int>();
    log_type<int>();

    // // error: invalid use of incomplete type ‘struct DebugType<std::basic_istream<char> >
    // debug_type(std::cin);
    log_type(std::cin);
    return 0;

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接