分类类型比较

decltype comparison

本文关键字:比较 类型 分类      更新时间:2023-10-16

有没有办法比较C++11中decltype的结果?

换句话说,为什么这段代码无效:

template<typename T, typename U>
void func(T& t, U& u) {
    if(decltype(t) == decltype(u)) {
        // Some optimised version for this case
    } else {
        // A more general case for differing types
    }
}

我知道在某些情况下,这个特殊问题可以通过部分模板专业化来解决;我的问题是关于decltype的比较。

编辑:这个问题是在尝试通过SFINAE为自由功能提供默认值的过程中出现的。 也许一个更好的问题是为什么这是无效的:

template<bool B>
bool SomeFunction() { ... }
template<typename T, typename U>
bool SomeFunctionWrapper(T& t, U& u) {
    SomeFunction<decltype(t) == decltype(u)>();
}

此后,我找到了另一种解决方案(根本不涉及模板),但在某个阶段我尝试了这个:

// If it exists, the free function is defined as
// bool AFreeFunction();
typedef struct { char } undefined;
template<typename T = void>
undefined AFreeFunction();
template<bool B>
bool AFreeFunctionWrapper_() {
    return false;
}
template<>
bool AFreeFunctionWrapper_<false>() {
    return AFreeFunction();
}
bool AFreeFunctionWrapper() {
    return AFreeFunctionWrapper_<decltype(AFreeFunction()) == decltype(undefined)>();
}

我最终得到了使用 GCC 4.6 的这种策略的变体,但随后发现 MSVC 中的模板函数不允许默认模板参数,即使在 2012 RC 中也是如此。 因此,最终的解决方案如下所示:

class AFreeFunction {
public:
    operator bool() { return false; }
};

如果定义了该函数,则会调用该函数。 如果不是,则将其解释为类的构造函数,然后将其隐式转换为bool

您通常通过标记调度来解决此问题。此外,您已经拥有tu的"声明类型" - 分别为T&U&。要比较相等的类型,可以使用 std::is_same 。但是,重载解决方案已经为您解决了这个问题:

template<class T>
void f(T& v1, T& v2){ ... } // #1
template<class T, class U>
void f(T& t, U& u){ ... } // #2

如果 f 的两个参数属于同一类型,则 #1 比 #2 更专业。如果您出于某种原因坚持通过手动类型比较来解决此问题,那么应用前面提到的几点会是什么样子:

#include <type_traits>
namespace detail{
template<class T, class U>
void f(T& t, U& u, std::true_type){ ... } // #1
template<class T, class U>
void f(T& t, U& u, std::false_type){ ... } // #2
} // detail::
template<class T, class U>
void f(T& t, U& u){
  detail::f(t, u, std::is_same<T,U>()); // tag dispatching
}

如果两种类型相同,std::is_same将从std::true_type派生,如果不是,则从std::false_type派生。

为什么无效?decltype的结果是一种类型。所以它说的是类似

if (int == int)

语言显然不允许。

您需要将函数的两个部分分开,并将专用部分放在专用类的函数中,然后将调用转发到那里。这很痛苦。

或者,如果您的实现正确实现了typeid或运行时类型信息,则可以使用它,尽管这会将所有内容推迟到程序运行时(这允许较少的优化)。

您可以使用

SFINAE(std::enable_if

):
template<typename T, typename U>
typename std::enable_if<std::is_same<T, U>::value, void>::type func(T& t, U& u) {
    std::cout << "samen";
}
template<typename T, typename U>
typename std::enable_if<!std::is_same<T, U>::value, void>::type func(T& t, U& u) {
    std::cout << "differentn";
}

正如Mehrdad所说,decltype(t)decltype(u)是类型(分别为T &U &),而不是值,因此不能在价值表达级别进行比较,而必须在元表达式(模板)级别进行比较。