【问题标题】:Ambigious access on variadic template multi inheritence function call [duplicate]可变参数模板多继承函数调用的模糊访问[重复]
【发布时间】:2015-11-09 17:54:48
【问题描述】:

所以,我正在研究如何解决Looking for design pattern to reduce virtual method overloads中的问题的解决方案

我的想法是使用可变参数模板来描述特定类可以接受哪些类型。这可能有一个小用例,但我喜欢玩模板...

这是我想出的(到目前为止):

struct Struct
{
    virtual void doit() = 0;
};

struct StructA : Struct
{
    void doit() { std::cout << "A" << std::endl; }
};

struct StructB : Struct
{
    void doit() { std::cout << "B" << std::endl; }
};

struct StructC : Struct
{
    void doit() { std::cout << "C" << std::endl; }
};

template <typename Type>
struct Accepter
{
    void accept(const Type& t) { t.doit(); };
};

template <typename...Types>
struct MultiAccepter : Accepter<Types>... {};

当只将一个类型传递给MultiAccepter 时,一切都会按其应有的方式进行。 只有当我传递 2 个或更多模板参数类型时,才会出现问题。 看起来编译器失去了区分不同类型的能力。

int main()
{
    StructA struct_a;
    StructB struct_b;

    Accepter<StructA>                           accept_a;
    Accepter<StructB>                           accept_b;
    MultiAccepter<StructA>                      accept_multi_a;
    MultiAccepter<StructB>                      accept_multi_b;
    MultiAccepter<StructA, StructB>             accept_multi_ab;



    accept_a.accept(struct_a);              //OK
    accept_b.accept(struct_b);              //OK
    accept_multi_a.accept(struct_a);        //OK
    accept_multi_b.accept(struct_b);        //OK
    accept_multi_ab.accept(struct_a);       //NOK:
                                            //  error C2385: ambiguous access of 'accept'
                                            //      note : could be the 'accept' in base 'Accepter<StructA>'
                                            //      note : or could be the 'accept' in base 'Accepter<StructB>'
    accept_multi_ab.accept(struct_b);       //NOK:
                                            //  error C2385: ambiguous access of 'accept'
                                            //      note : could be the 'accept' in base 'Accepter<StructA>'
                                            //      note : or could be the 'accept' in base 'Accepter<StructB>'
                                            //  error C2664 : 'void Accepter<StructA>::accept(const Type &)' : cannot convert argument 1 from 'StructB' to 'const StructA &'
                                            //      with
                                            //      [
                                            //          Type = StructA
                                            //      ]
                                            //      note : Reason : cannot convert from 'StructB' to 'const StructA'
                                            //      note : No user - defined - conversion operator available that can perform this conversion, or the operator cannot be called
    return 0;
}

尝试使用gcc 5.2 编译代码也不起作用: http://goo.gl/oVLHT8

我想这只是一个简单的问题,但我就是找不到解决方案。 有人知道我做错了什么吗?


P.S.: 这边的例子描述了一个类似的模式: http://natsys-lab.blogspot.de/2013/07/c-variadic-templates-and-multiple.html


更新:看起来基类Accepter&lt;StructB&gt;定义了一个函数void accept(const StructA&amp;)。我还是不明白为什么会这样。

【问题讨论】:

  • 这是骗人的……某事。如果没有 using 声明,来自不同基类范围的名称不会重载。
  • @T.C.正确的。它需要一个可变参数 using 指令,我不知道该怎么做。另请注意stackoverflow.com/questions/7870498/…
  • @T.C. This?甚至有相同的评论来自你

标签: c++ templates inheritance c++14 multiple-inheritance


【解决方案1】:

我使用此处描述的模式提出了一个解决方案:https://stackoverflow.com/a/28349054/1149664

诀窍是一次继承一个基类Accepter&lt;T0&gt;,然后将其余类型推向继承链的更上游。我还使方法 const 使其保持一致。您可以根据需要随意调整。

#include "stdafx.h"
#include <functional>
#include <chrono>
#include <iostream>


struct Struct
{
    virtual void doit() const = 0;
};

struct StructA : public Struct
{
    void doit() const { std::cout << "A" << std::endl; }
};

struct StructB : public Struct
{
    void doit() const { std::cout << "B" << std::endl; }
};

struct StructC : public Struct
{
    void doit() const { std::cout << "C" << std::endl; }
};

template <typename Type>
struct Accepter
{
    void accept(const Type& t) const { t.doit(); } ;
};

template <typename... Types>
struct MultiAccepter;

template <typename T0, typename...Types>
struct MultiAccepter<T0, Types...> : public Accepter<T0>, public MultiAccepter<Types...> {
    using Accepter<T0>::accept;
    using MultiAccepter<Types...>::accept;
};

template <typename T0>
struct MultiAccepter<T0> : public Accepter<T0> {
    using Accepter<T0>::accept;
};

int main()
{
    StructA struct_a;
    StructB struct_b;

    Accepter<StructA>                           accept_a;
    Accepter<StructB>                           accept_b;
    MultiAccepter<StructA>                      accept_multi_a;
    MultiAccepter<StructB>                      accept_multi_b;
    MultiAccepter<StructA, StructB>             accept_multi_ab;

    accept_a.accept(struct_a);              
    accept_b.accept(struct_b);             
    accept_multi_a.accept(struct_a);       
    accept_multi_b.accept(struct_b);     
    accept_multi_ab.accept(struct_a);    
    accept_multi_ab.accept(struct_b);     
    return 0;
}

【讨论】:

  • 非常感谢。这行得通。
猜你喜欢
  • 1970-01-01
  • 2014-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多