使用std :: is_same和operator ||进行编译错误
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用std :: is_same和operator ||进行编译错误相关的知识,希望对你有一定的参考价值。
我不明白为什么下面的代码用Clang ++编译,而不是用g ++编译。
#include <memory>
class A {
public:
virtual ~A() {}
};
class B : public A {
public:
virtual ~B() {}
};
template <typename Base, typename T>
inline bool isInstanceOf(const T& object) {
// This line compiles with clang++ (7.0.1) and with gcc (8.3.1)
// return std::is_same<Base, T>::value ? true : (dynamic_cast<const Base*>(&object) != nullptr);
// This line compiles only with clang++
return std::is_same<Base, T>::value || dynamic_cast<const Base*>(&object) != nullptr;
}
int main() {
isInstanceOf<A>(B());
isInstanceOf<A>(A()); // Compilation fails
return 0;
}
编译错误:
$> g++ -o bin -Wall -Werror test.cpp
test.cpp: In instantiation of 'bool isInstanceOf(const T&) [with Base = A; T = A]':
test.cpp:24:24: required from here
test.cpp:19:79: error: the compiler can assume that the address of 'object' will never be NULL [-Werror=address]
std::is_same<Base, T>::value || dynamic_cast<const Base*>(&object) != nullptr;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
cc1plus: all warnings being treated as errors
为什么模板实例化不会跳过测试的第二部分?
以下代码也编译:
if (std::is_same<Base, T>::value) {
return true;
} else {
return dynamic_cast<const Base*>(&object) != nullptr;
}
以下代码的编译也失败了:
if (std::is_same<Base, T>::value) {
return true;
}
return dynamic_cast<const Base*>(&object) != nullptr;
(这不是'真正的'答案,但使用答案比使用评论更实际)
我对你的代码有相同的行为,但奇怪的是没有警告/错误替换
return dynamic_cast<const Base*>(&object) != nullptr;
通过
const T * pobject = &object;
return std::is_same<Base, T>::value || dynamic_cast<const Base*>(pobject) != nullptr;
#include <memory>
class A {
public:
virtual ~A() {}
};
class B : public A {
public:
virtual ~B() {}
};
template <typename Base, typename T>
inline bool isInstanceOf(const T& object) {
const T * pobject = &object;
return std::is_same<Base, T>::value || dynamic_cast<const Base*>(pobject) != nullptr;
}
int main() {
isInstanceOf<A>(B());
isInstanceOf<A>(A()); // Compilation fails
return 0;
}
编译(gcc版本6.3.0)
pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -Wall -Werror b.cc
pi@raspberrypi:/tmp $
此代码不会给您一个错误,而是一个警告。在我看来,它在这里很有帮助。警告是你可以选择忽略的东西,但在这种情况下,它正在提出一个有用的观点:dynamic_cast
ing一个类型到它的基类将永远不会返回一个NULL
,并且由于这是一个引用类型,编译器期望它不是一个NULL
指针当你拿到它的地址。
这段代码:
if (std::is_same<Base, T>::value) {
return true;
} else {
return dynamic_cast<const Base*>(&object) != nullptr;
}
...编译,因为现在你引入的情况dynamic_cast
可能确实会给你一个NULL
,因为可能无法向Base
施放。 G ++没有在这里警告你这是正确的。
对我来说,这是GCC给你提供比Clang更完整的警告的情况,而不是GCC缺陷的情况,告诉你在某些模板实例化下不会执行的代码。
以下代码也编译时没有警告:
template <typename Base, typename T>
bool isInstanceOf(const T& object) {
if (!std::is_same<Base, T>::value) {
return dynamic_cast<const Base*>(&object) != nullptr;
}
}
或者这一个:
template <typename Base, typename T>
inline bool isInstanceOf(const T* pointer) {
return dynamic_cast<const Base*>(pointer) != nullptr;
}
template <typename Base, typename T>
inline bool isInstanceOf(const T& object) {
return std::is_same<Base, T>::value || isInstanceOf<Base>(&object);
}
@cyberbisson:你可能是对的,应该是GCC完成的代码分析缺乏。
我不确定什么是解决我的问题的最佳语法(或更可读/可理解)。 “if / else”选项导致clang-tidy(readability-else-after-return)出现问题
目前我选择了“三元运算符”变体,但我喜欢“两个函数”之一。
我认为c ++ 17解决方案也可以
if constexpr (std::is_same<Base, T>::value) {
return true;
} else {
return dynamic_cast<const Base*>(&object) != nullptr;
}
以上是关于使用std :: is_same和operator ||进行编译错误的主要内容,如果未能解决你的问题,请参考以下文章
C++11的std::is_same和std::decay使用与源码解析