[英]specialize a c++ template function when two types are the same
My use case is the following. 我的用例如下。 Given an object I want a readable means of determining if that object is a subclass of another object.
给定一个对象,我想要一种可读的方法来确定该对象是否是另一个对象的子类。 Obviously at the core is a call to
dynamic_cast
, but I want something more readable. 显然,核心是对
dynamic_cast
的调用,但是我想要更易读的东西。 So I have the following: 所以我有以下几点:
template <typename C, typename T>
bool isInstanceOf(const T& t) noexcept {
if (typeid(t) == typeid(C)) {
return true;
}
if (dynamic_cast<const C*>(&t) != nullptr) {
return true;
}
return false;
}
This works as intended, but if I make a call where C and T are in fact the same type, I get a compiler warning on the dynamic_cast because the compiler knows it will never return null. 这按预期工作,但是如果我在C和T实际上是相同类型的地方进行调用,则会在dynamic_cast上收到编译器警告,因为编译器知道它永远不会返回null。 This leads me to my question which is: can I write a specialized version of this that simply returns true if C and T are in fact the same type.
这引出了我的问题:是否可以编写一个专门的版本,如果C和T实际上是同一类型,则仅返回true。
I tried the obvious 我尝试了明显的
template <typename C>
inline bool isInstanceOf(const C& t) noexcept {
return true;
}
but that gives me an error of "Call to 'isInstanceOf' is ambiguous." 但这给我一个错误:“对'isInstanceOf'的调用是模棱两可的”。
This isn't really a high-priority item as I would never actually call isInstanceOf<B>(b)
where I know b is of type B, but I have it in my unit tests for completeness and would like to see if there is a way to get the compiler to optimize it out without giving the warning. 这并不是真正的高优先级项目,因为我永远不会真正调用
isInstanceOf<B>(b)
,因为我知道b的类型为B,但是为了确保完整性,我在单元测试中使用了它,我想看看是否存在一种使编译器在不发出警告的情况下对其进行优化的方法。
In case it help, here is the warning message I receive: 如果有帮助,这是我收到的警告消息:
In file included from Tests/rtti.cpp:15:0:
.build/Linux-x86_64/include/kss/util/rtti.hpp: In instantiation of ‘bool kss::util::rtti::isInstanceOf(const T&) [with C = {anonymous}::B; T = {anonymous}::B]’:
Tests/rtti.cpp:81:9: required from here
.build/Linux-x86_64/include/kss/util/rtti.hpp:61:40: warning: the compiler can assume that the address of ‘t’ will never be NULL [-Waddress]
if (dynamic_cast<const C*>(&t) != nullptr) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
If you have C++17, you might use if constexpr
: 如果您拥有C ++ 17,则可以使用
if constexpr
:
template <typename C, typename T>
bool isInstanceOf(const T& t) noexcept {
if constexpr (std::is_same<T, C>::value) {
return true;
} else {
return dynamic_cast<const C*>(&t) != nullptr;
}
}
Prior C++17, overloads and SFINAE (or tag dispatching) might do the job: 在C ++ 17之前的版本中,重载和SFINAE(或标签分配)可能会完成以下任务:
template <typename C>
bool isInstanceOf(const C& t) noexcept {
return true;
}
template <typename C, typename T>
std::enable_if_t<!std::is_same<C, T>::value, bool>
isInstanceOf(const T& t) noexcept {
return dynamic_cast<const C*>(&t) != nullptr;
}
Not exactly what you asked and mainly for fun but... what about a couple of template overloaded functions as follows 不完全是您的要求,主要是为了娱乐,但是...几个如下的模板重载函数呢?
template <typename T>
bool isIstanceOf (T const &) noexcept
{ return true; }
template <typename>
bool isIstanceOf (...) noexcept
{ return false; }
that you have to call explicating the type T
? 你必须打电话说明类型
T
吗?
But is more "is-convertible-to" than "is-instance-of". 但是,“可转换为”比“可转换为”更多。
The following is a full compiling example 以下是完整的编译示例
#include <iostream>
template <typename T>
bool isIstanceOf (T const &) noexcept
{ return true; }
template <typename>
bool isIstanceOf (...) noexcept
{ return false; }
struct A
{ };
struct B : public A
{ };
int main()
{
A a;
B b;
std::cout << isIstanceOf<A>(a) << std::endl; // print 1
std::cout << isIstanceOf<A>(b) << std::endl; // print 1
std::cout << isIstanceOf<B>(a) << std::endl; // print 0
std::cout << isIstanceOf<B>(b) << std::endl; // print 1
std::cout << isIstanceOf<int>(a) << std::endl; // print 0
std::cout << isIstanceOf<int>(b) << std::endl; // print 0
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.