我正在尝试为BinaryTree Operations创建项目,以下是带有代码的类原型,我遇到了问题。
BinaryTree.h文件中的BinaryTree类
template <class T>
class BinaryTree
{
public:
BinaryTree();
BinaryTree(T);
};
BinaryTree.cpp中的构造函数实现
template<class T>
struct isPointer
{
static const bool value=false;
};
template<class T>
struct isPointer<T*>
{
static const bool value=true;
};
template<class T>
BinaryTree<T>::BinaryTree():root(nullptr)
{
//ctor
}
template<class T>
BinaryTree<T>::BinaryTree(T data)
{
if(isPointer<T>::value == true)
{
if(data != nullptr)
{
//Do something
}
}
}
BinaryTreeOperations类继承BinaryTree类,其原型在BinaryTreeOperations.h中定义
template<class T>
class BinaryTreeOperations:public BinaryTree<T>
{
public:
//Constructors
BinaryTreeOperations();
BinaryTreeOperations(T);
};
虽然构造函数是在BinaryTreeOperations.cpp类中定义的
template<class T>
BinaryTreeOperations<T>::BinaryTreeOperations(T data):BinaryTree<T>(data)
{
//ctor
}
Main.cpp文件中的主要功能
int main()
{
cout << "Hello world!" << endl;
BinaryTreeOperations<std::string> b("1");
}
现在g ++抛出的错误是
与'operator!='不匹配(操作数类型为 'std :: __ cxx11 :: basic_string'和'std :: nullptr_t')
在第
行if(data != nullptr)
在BinaryTree.cpp类中定义的BinaryTree构造函数中的
问题就出现了。我已经定义了isPointer结构来检查给定的模板是否是指针。但看起来,尽管T是std :: string g ++正在进入if(isPointer<T>::value == true)
条件。
我不明白我做错了什么?任何形式的指导都将深受赞赏。
答案 0 :(得分:2)
if(isPointer<T>::value == true)
{
if(data != nullptr)
{
//Do something
}
}
这将为每个T
编译。即使对于给定的T
,表达式isPointer<T>::value
将评估为false,但整个事情将被编译。如果data
,T
的实例无法与nullptr
进行比较,则会导致编译失败。
C ++ 17引入了static_if
,这是一个编译时指令,它根据编译时constexpr
选择性地编译代码块(本身就是一个有点引起争议的补充)。在C ++ 17之前,除了isPointer
的特化之外,正确执行此操作的唯一方法是使用特化来有选择地编译这一块代码。
但是,无论如何,编译错误的答案是它等同于:
std::string data;
if (0)
{
if (data != nullptr)
{
// ...
}
}
有问题的代码永远不会到达的事实并没有改变它必须是有效的,可编译的C ++代码这一事实。
答案 1 :(得分:2)
这是constexpr if(C ++ 17)一个很好的补充:你的分支将在编译时评估你传递的每个T
可能的解决方法是利用enable_if并根据isPointer
谓词的结果定义两个构造函数版本,并让SFINAE完成其工作
template <class T>
class BinaryTree
{
public:
BinaryTree();
template<typename TT = T>
BinaryTree(TT, typename std::enable_if<!isPointer<TT>::value>::type * = nullptr) {
}
template<typename TT = T>
BinaryTree(TT data, typename std::enable_if<isPointer<TT>::value>::type * = nullptr) {
if (data != nullptr)
{
//Do something (this is a pointer)
}
}
};
或者重构您的代码,记住模板完全是模板的事实,并且在实例化时,它将在任何它定义的代码分支。
答案 2 :(得分:1)
但看起来,尽管T是std :: string g ++正处于
if(isPointer<T>::value == true)
状态。
事实上。整个函数将被编译。执行能否达到这种比较是无关紧要的。
解决方案:编写一个函数模板并将其重载为指针。
template<class T>
void do_something(const T&) {
// do nothing
}
template<class T>
void do_something(T* data) {
if(data != nullptr) {
// do something
}
}
// ...
template<class T>
BinaryTree<T>::BinaryTree(T data)
{
do_something(data);
}
C ++ 17计划引入constexpr if,这将允许您在单个函数中就地编写条件编译时间。