分类类型比较
decltype comparison
有没有办法比较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
。
您通常通过标记调度来解决此问题。此外,您已经拥有t
和u
的"声明类型" - 分别为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 &
),而不是值,因此不能在价值表达级别进行比较,而必须在元表达式(模板)级别进行比较。
- 将模板化的类型与C++中的某些类/类型进行比较
- C++中"std::sort"比较器的不同类型
- 比较两个整数在C++中与未知 int 类型的相等性
- 如何使用变量模板比较 C++ 17 中的变量类型?
- 比较LLVM值的类型
- 用于比较基元类型的std::可选的有趣程序集
- 在C++中返回基元类型数组(Java比较)
- 为模板类中的特定类型编写比较器函数
- 为什么比较函数类型需要指定为模板参数?
- C++,"由于数据类型范围有限,比较总是正确的"
- 如何在C++中比较 lambda 函数的返回类型?
- C++ - 比较模板和类之间的数据类型
- 类型ID指针和引用比较差异?
- 在C++中,您能否像比较类型一样比较模板
- 使用具有自定义比较类型的关联容器时出现的问题
- 在Template中设置默认比较类型
- STL中使用的C++自定义比较类型(函数谓词与较少结构)
- C++类型比较:类型 ID 与双重调度dynamic_cast
- 比较类型指针
- double比较类型的变量总是返回false