6

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

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

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
    }
}

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

编辑:在尝试通过 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.

4

3 回答 3

9

您通常通过标签调度来解决这个问题。此外,您已经分别拥有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_samestd::true_type如果两种类型相同,则将派生自,否则将派生自std::false_type

于 2012-08-08T10:44:54.333 回答
6

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

if (int == int)

这显然是语言不允许的。

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

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

于 2012-08-08T09:35:31.473 回答
4

您可以使用 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 << "same\n";
}
template<typename T, typename U>
typename std::enable_if<!std::is_same<T, U>::value, void>::type func(T& t, U& u) {
    std::cout << "different\n";
}

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

于 2012-08-08T10:00:47.433 回答