Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么是导致这种超负荷解决头痛的原因?_C++_Templates_Traits_Crtp_Overload Resolution - Fatal编程技术网

C++ 什么是导致这种超负荷解决头痛的原因?

C++ 什么是导致这种超负荷解决头痛的原因?,c++,templates,traits,crtp,overload-resolution,C++,Templates,Traits,Crtp,Overload Resolution,我有一个程序,其中有很多嵌套的if/switch语句,它们在几个地方重复。我尝试将其提取出来,并将开关放入模板方法类中,然后允许客户端使用重载来重载他们想要专门处理的开关分支: class TraitsA {}; class TraitsB : public TraitsA {}; class Foo { bool traitsB; public: // Whether or not a Foo has traitsB is determined at runtime. It

我有一个程序,其中有很多嵌套的if/switch语句,它们在几个地方重复。我尝试将其提取出来,并将开关放入模板方法类中,然后允许客户端使用重载来重载他们想要专门处理的开关分支:

class TraitsA {};
class TraitsB : public TraitsA {};

class Foo
{
    bool traitsB;
public:
    // Whether or not a Foo has traitsB is determined at runtime. It is a
    // function of the input to the program and therefore cannot be moved to
    // compile time traits (like the Iterators do)
    Foo() : traitsB(false) {}
    virtual ~Foo() {}
    bool HasTraitsB() const { return traitsB; }
    void SetTraitsB() { traitsB = true; }
};

class SpecificFoo : public Foo
{
};

template <typename Client> //CRTP
class MergeFoo
{
protected:
    Foo DoMerge(Foo&, const Foo&, int, TraitsA)
    {
        // Do things to merge generic Foo
    }
public:
    // Merge is a template method that puts all the nasty switch statements
    // in one place.
    // Specific mergers implement overloads of DoMerge to specify their
    // behavior...
    Foo Merge(Foo* lhs, const Foo* rhs, int operation)
    {
        const Client& thisChild = *static_cast<const Client*>(this);

        SpecificFoo* lhsSpecific = dynamic_cast<SpecificFoo*>(lhs);
        const SpecificFoo* rhsSpecific = dynamic_cast<const SpecificFoo*>(rhs);

        // In the real code these if's are significantly worse
        if (lhsSpecific && rhsSpecific)
        {
            if (lhs->HasTraitsB())
            {
                return thisChild.DoMerge(*lhsSpecific, 
                               *rhsSpecific, 
                               operation,
                               TraitsB());
            }
            else
            {
                return thisChild.DoMerge(*lhsSpecific,
                               *rhsSpecific,
                               operation,
                               TraitsA());
            }
        }
        else
        {
            if (lhs->HasTraitsB())
            {
                return thisChild.DoMerge(*lhs, *rhs, operation, TraitsB());
            }
            else
            {
                return thisChild.DoMerge(*lhs, *rhs, operation, TraitsA());
            }
        }
    }
};

class ClientMergeFoo : public MergeFoo<ClientMergeFoo>
{
    friend class MergeFoo<ClientMergeFoo>;
    Foo DoMerge(SpecificFoo&, const SpecificFoo&, int, TraitsA)
    {
        // Do things for specific foo with traits A or traits B
    }
};

class ClientMergeFooTwo : public MergeFoo<ClientMergeFoo>
{
    friend class MergeFoo<ClientMergeFooTwo>;
    Foo DoMerge(SpecificFoo&, const SpecificFoo&, int, TraitsB)
    {
        // Do things for specific foo with traits B only
    }
    Foo DoMerge(Foo&, const Foo&, int, TraitsA)
    {
        // Do things for specific foo with TraitsA, or for any Foo
    }
};
类TraitsA{};
B类列车:公共列车{};
福班
{
布尔特拉茨b;
公众:
//Foo是否有traitsB是在运行时确定的
//程序输入的功能,因此不能移动到
//编译时特性(就像迭代器一样)
Foo():traitsB(false){}
虚拟~Foo(){}
bool HasTraitsB()常量{return traitsB;}
void SetTraitsB(){traitsB=true;}
};
类特定Foo:公共Foo
{
};
模板//CRTP
类MergeFoo
{
受保护的:
Foo-DoMerge(Foo&,const-Foo&,int,TraitsA)
{
//做一些事情来合并通用Foo
}
公众:
//Merge是一个模板方法,它可以放置所有讨厌的switch语句
//在一个地方。
//特定合并实现DoMerge的重载以指定它们的
//行为。。。
Foo合并(Foo*lhs、const Foo*rhs、int操作)
{
const Client&thisChild=*静态_cast(this);
SpecificFoo*LHSSSpecific=动态施法(lhs);
常量SpecificFoo*rhssspecific=动态施法(rhs);
//在实际代码中,这些if的情况要严重得多
if(左侧特定和右侧特定)
{
如果(lhs->HasTraitsB())
{
返回此子项。DoMerge(*lhsSpecific,
*rhsSpecific,
活动
TraitsB());
}
其他的
{
返回此子项。DoMerge(*lhsSpecific,
*rhsSpecific,
活动
TraitsA());
}
}
其他的
{
如果(lhs->HasTraitsB())
{
返回thisChild.DoMerge(*lhs,*rhs,operation,TraitsB());
}
其他的
{
返回thisChild.DoMerge(*lhs,*rhs,operation,TraitsA());
}
}
}
};
类ClientMergeFoo:publicmergefoo
{
朋友类合并;
Foo-DoMerge(特定Foo和,常量特定Foo和,int,TraitsA)
{
//用特征A或特征B为特定的食物做事
}
};
类ClientMergeFooTwo:publicmergefoo
{
朋友类合并;
Foo-DoMerge(SpecificFoo&,const SpecificFoo&,int,TraitsB)
{
//只为特性B的特定foo做事
}
Foo-DoMerge(Foo&,const-Foo&,int,TraitsA)
{
//用TraitsA为特定的foo或任何foo做事情
}
};
但是,这无法编译(至少在
ClientMergeFooTwo
的情况下),因为它无法将Foo&转换为特定的Foo&。你知道为什么它没有在
MergeFoo
中选择完美的泛型重载,而未能通过转换吗

编辑:这个psuedocode示例显然做得不太好,因为我尝试编写它的速度太快了。我已经纠正了一些错误…

constthischild&=*static\u cast(this);
const thisChild& = *static_cast<const Client*>(this);
我不明白这个?类型(或变量)在哪里?你是说:

const Client & thisChild = *static_cast<const Client*>(this);
const-Client&thisChild=*静态_-cast(this);
在下面

SpecificFoo* rhsSpecific = dynamic_cast<const SpecificFoo*>(rhs);
SpecificFoo*rhssspecific=dynamic\u cast(rhs);
常量中存在不匹配,例如在您忘记的目标中
const

类ClientMergeFooTwo:public MergeFoo
class ClientMergeFooTwo : public MergeFoo<ClientMergeFoo>

这可能是问题的原因。

可能需要更多关于它失败的地方的信息,但是为了完成您想要做的事情,您需要在MergeFoo的公共合并函数中调用Client::DoMerge(),而不仅仅是调用DoMerge()

你知道为什么它没有在MergeFoo中选择完美的泛型重载,而没有通过这种转换吗

是的,因为名字隐藏规则。如果派生类中的函数与基类中的函数具有相同的名称,则基类函数是“隐藏的”,它甚至不查看相关函数的参数


也就是说,解决方案很简单:使用公共部分中的MergeFoo::DoMerge使用一个简单的
使基类版本在派生类中可用。

发布错误,同时指示行号。@Nawaz:我不能--这不是原始代码,我不能在这里发布原始代码。它无法编译对
DoMerge
的调用,并且由于隐式转换而失败。您的示例是否在您的框中实际失败?我刚刚用VS2010测试了它,没有错误。你在所有方面都是正确的。我对真实代码的拙劣拼凑模仿太快了:(对DoMerge的一个调用失败了。我不认为调用
Client::DoMerge
是明确要求的,因为我已经将
this
转换为
Client
类型。你这样做了,但是你需要调用这个孩子。DoMerge()为了得到想要的效果。叹气:我对这段代码的想法的抄写是可怕的!