C++ C++;-奇怪的情况是,模板是\u指针似乎失败了
我正在尝试为BinaryTree操作创建项目,下面是带有代码的类原型,我在其中遇到了问题 BinaryTree.h文件中的BinaryTree类C++ C++;-奇怪的情况是,模板是\u指针似乎失败了,c++,c++11,templates,template-meta-programming,C++,C++11,Templates,Template Meta Programming,我正在尝试为BinaryTree操作创建项目,下面是带有代码的类原型,我在其中遇到了问题 BinaryTree.h文件中的BinaryTree类 template <class T> class BinaryTree { public: BinaryTree(); BinaryTree(T); }; 在BinaryTree.cpp类中定义的BinaryTree构造函数中 template<class T> BinaryTr
template <class T>
class BinaryTree
{
public:
BinaryTree();
BinaryTree(T);
};
在BinaryTree.cpp类中定义的BinaryTree构造函数中
template<class T>
BinaryTreeOperations<T>::BinaryTreeOperations(T data):BinaryTree<T>(data)
{
//ctor
}
问题来了。我已经定义了isPointer结构来检查给定模板是否为指针。但是看起来,尽管T是std::string,g++在if(isPointer::value==true)
条件
我不明白我做错了什么?我们将非常感谢任何形式的指导
if(isPointer<T>::value == true)
{
if(data != nullptr)
{
//Do something
}
}
<> P>一个事实,即代码永远不会达到,它不会改变它必须是有效的,可编译的,C++代码的事实。
但是看起来,尽管T是std::string,g++仍处于if(isPointer::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);
}
模板
void do_某事(const T&){
//无所事事
}
模板
void do_something(T*数据){
如果(数据!=nullptr){
//做点什么
}
}
// ...
模板
二进制树::二进制树(T数据)
{
做某事(数据);
}
计划引入C++17,这将允许您在单个函数中就地编写编译时条件。对于这种情况,(C++17)将是一个很好的补充:您的分支将在编译时对通过的每个T进行评估 一种可能的解决方法是根据
isPointer
谓词的结果,利用并定义两个构造函数版本,并让其完成工作
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)
}
}
};
模板
类二叉树
{
公众:
二叉树();
模板
二进制树(TT,typename std::enable_if::value>::type*=nullptr){
}
模板
二进制树(TT数据,typename std::enable_if::type*=nullptr){
如果(数据!=nullptr)
{
//做点什么(这是一个指针)
}
}
};
或者重构你的代码,记住一个模板就是一个模板,当它被实例化时,它将为它定义的任何代码分支上的参数生成代码。
如果
是严格的运行时检查,两个分支都必须正确编译,即使其中一个已失效。@Bathsheba将使用std::is_pointer给我一个不同的结果。是:两个重载,一个用于指针,一个用于非指针,使用调度。的可能重复。考虑使用重载,因为@ Quentin suggestedYou也应该查看如果(0)表示错误。你的意思是如果(1)。还有任何关于这个可怕错误的建议。不,我特别指的是if(0)
,问题中导致编译错误的同等情况,当T
是std::string
时会发生编译错误。另外,我也不会确切地称之为“可怕”错误。模板实例化的一个相当常见、神秘的方面经常被误解。谢谢。@Quentin先生在问题的评论中提到了使用std::enable_if进行调度。我从来没有使用过enable_,如果你能用同样的方法指导我一点。@Dr.Xperience你不一定需要enable_if
,在这种情况下,它只会让这个程序稍微冗长一些。然而,如果您使用的是一个更复杂的特征条件,您的isPointer
,那么避免重复多个专门化是很有用的。我建议您看看stackoverflow的现有答案,了解如何使用它。感谢bro提供了使用enable_if的解决方案。我不熟悉enable_if的概念。现在我想标记两个解决方案作为我问题的答案。在接受字符串文本的函数上使用此函数时,我面临一个奇怪的问题<代码>模板无效测试(TT数据){std::coutOh我得到了它我应该做无效测试(T数据)
而不是无效测试(TT数据)
我的错误。
if(data != nullptr)
if(isPointer<T>::value == true)
{
if(data != nullptr)
{
//Do something
}
}
std::string data;
if (0)
{
if (data != nullptr)
{
// ...
}
}
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);
}
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)
}
}
};