我的用例如下。给定一个对象,我想要一种可读的方法来确定该对象是否是另一个对象的子类。显然,核心是对dynamic_cast
的调用,但我想要更具可读性的东西。所以我有以下内容:
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;
}
这按预期工作,但是如果我在C和T实际上是同一类型的情况下进行调用,我会在dynamic_cast上收到编译器警告,因为编译器知道它永远不会返回null。这引出了我的问题:如果C和T实际上是同一类型,我可以编写一个专门的版本,只返回true。
我试过了明显的事
template <typename C>
inline bool isInstanceOf(const C& t) noexcept {
return true;
}
但这给了我一个错误,“调用'isInstanceOf'是模棱两可的。”
这不是一个高优先级的项目,因为我永远不会实际调用isInstanceOf<B>(b)
,我知道b是B类型,但我在单元测试中有完整性,并希望看看是否有办法获得编译器在没有发出警告的情况下优化它。
如果有帮助,这是我收到的警告信息:
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) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
如果你有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;
}
}
在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;
}
不完全是你问的,主要是为了好玩,但是...如下所示的几个模板重载函数
template <typename T>
bool isIstanceOf (T const &) noexcept
{ return true; }
template <typename>
bool isIstanceOf (...) noexcept
{ return false; }
你必须打电话说明T
类型?
但是比“is-instance-of”更“可转换为”。
以下是完整的编译示例
#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
}