首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有压缩对的模糊基类转换

具有压缩对的模糊基类转换
EN

Stack Overflow用户
提问于 2015-03-01 00:37:07
回答 2查看 487关注 0票数 0

因此,我尝试使用空基优化创建一个压缩对。我希望这样,如果类ab是空的,那么compressed_pair<a, b>也是空的。所以我定义了我的压缩对,如下所示:

代码语言:javascript
运行
复制
template <class First, class Second>
struct compressed_pair : First, Second 
{
    compressed_pair() {}
    compressed_pair(const First& x, const Second & y)
    : First(x), Second(y) 
    {}
    First& first()  { return *this; }
    Second& second() { return *this; }
};

但是,如果其中一种类型继承自另一种类型,则会变得不明确。例如,当我编译这个程序时:

代码语言:javascript
运行
复制
struct a
{};

struct b : a
{};

int main()
{
    compressed_pair<a, b> p;
    auto x = p.first();
}

我从clang得到了这个错误:

代码语言:javascript
运行
复制
compressed_pair.cpp:8:30: error: ambiguous conversion from derived class 'compressed_pair<a, b>' to base class 'a':
    struct compressed_pair<struct a, struct b> -> struct a
    struct compressed_pair<struct a, struct b> -> struct b -> struct a
    First& first()  { return *this; }
                             ^~~~~
compressed_pair.cpp:21:16: note: in instantiation of member function 'compressed_pair<a, b>::first' requested here
    auto x = p.first();
               ^

那么,如何避免模棱两可的转换,使compressed_pair<a, b>仍然是空的呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-01 05:27:29

您所遇到的问题是,从compressed_pair中可以应用转换的两个基础。您需要能够驱动编译器选择其中之一。想到的第一件事是添加另一层继承,您可以将其用作选择器:

代码语言:javascript
运行
复制
template <int N, typename T>
struct element : T {};

template <typename T, typename U>
struct compressed_pair : element<0, T>, element<1, U> { ... };

那么访问器的实现可以是:

代码语言:javascript
运行
复制
template <typename T, typename U>
T& compressed_pair<T,U>::first() {
    return static_cast<element<0,T>&>(*this);
}

访问器内部的强制转换强制选择两个直接基( element<0,T> )中的一个。从那时起,只有一个T类型的基。

您还可以使用将访问器移动到该中间步骤,而不是将其设置为完整类型。最后,通过专门化,您应该能够为element提供一个支持非类类型的不同实现,因为当前的实现会阻塞int这样的类型。

票数 2
EN

Stack Overflow用户

发布于 2015-03-01 00:49:19

使用virtual继承可以避免歧义,或者要求FirstSecond不能相互派生。这是一项或两项决定。你需要决定是避免模棱两可还是允许空基优化对你来说更重要。

一般来说,为了避免模棱两可,继承不止一次(即由compressed_pair和其他结构类型继承)的对象需要是一个虚拟基础。由于模板可以使用任何方法实例化,这意味着FirstSecond都必须是compressed_pair的虚拟基础,而a必须是bvirtual基。

如果您始终知道Second可能是从First派生的,但是First永远不会从Second派生,那么您可以稍微放松一下(如果First是从Second派生的,那么再次使用模糊的代价)。

请记住,虚拟继承确实对类的工作方式施加了一些限制。例如,它影响基的构造顺序,要求任何后续派生类管理通过基类继承的虚拟基的构造,等等。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28788715

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档