这种超负荷解决头痛的原因是什么
What is the cause of this overload resolution headache?
我有一个程序,其中有很多嵌套的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
}
};
然而,这无法编译(至少在ClientMergeFooTwo
的情况下是这样(,说明它无法转换Foo&转换为SpecificFoo&。有什么想法吗?为什么它没有在MergeFoo
中选择完全好的泛型重载,而是失败了转换?
EDIT:好吧,考虑到我写的速度,这个伪代码示例显然做得不太好。我已经纠正了一些错误。。。
有什么想法吗?为什么它没有在MergeFoo中选择非常好的泛型重载,而是失败了转换?
是的,因为名字隐藏规则。如果派生类中的函数与基类中的函数同名,则基类函数是"隐藏的",它甚至不查看相关函数的参数。
也就是说,解决方案很简单:在公共部分使用简单的using MergeFoo::DoMerge
,使基类版本在派生类中可用。
const thisChild& = *static_cast<const Client*>(this);
我听不懂?类型(或变量(在哪里?你的意思是:
const Client & thisChild = *static_cast<const Client*>(this);
在下面的中
SpecificFoo* rhsSpecific = dynamic_cast<const SpecificFoo*>(rhs);
常量不匹配,就像您忘记了const
的目标一样。
可以使用更多关于它在哪里失败的信息,但看起来为了完成你想要做的事情,你需要在MergeFoo的公共Merge函数中调用Client::DoMerge((,而不仅仅是调用DoMerge(。
class ClientMergeFooTwo : public MergeFoo<ClientMergeFoo>
这可能是问题的原因。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- C++避免重复声明的语法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- C++中名称篡改的目的是什么
- 在 c++ 中拥有一组结构的正确方法是什么?
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 是什么阻止DOMTimerCoordinator::NextID进入无休止的循环
- 派生类销毁的最佳实践是什么
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 通过JNI传递数据数组的最快方法是什么
- "using namespace std;"在C++的作用是什么?
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 文件系统:复制功能的速度秘诀是什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 在C 中超负荷构造函数的合适方式是什么
- 这种超负荷解决头痛的原因是什么