【问题标题】:superclass operator() error - ambiguous超类运算符()错误 - 模棱两可
【发布时间】:2014-10-24 19:40:08
【问题描述】:

我正在尝试使用 C++11 定义一个可以存储多个 std::function<> 的类,并根据它们的参数类型调用它们,类似于重载解析。

我为“重载”函数应该支持的每个函数签名声明一个基类:

template <typename R, typename... A>
struct overload;

template <typename R, typename... A>
struct overload<R(A...)>
{
  typedef std::function<R(A...)> F;
  F f_;
  overload(F f): f_(f) {}
  R operator()(A... a)
  {
    return f_(a...);
  }
};

template <typename... T>
struct overloaded_function : public overload<T>...
{
  overloaded_function(T... t): overload<T>(t)... {}
};

int main()
{
  overloaded_function<void(float), void(int, int)> f([](float){}, [](int, int){});
  f(1.F);  // build error
  f(2, 3); // build error
  return 0;
}

构建错误:(Visual Studio 2013)

"overload::operator() [with R=void, A=]" 不明确 c:\Users\benj7280\Documents\kernel_builder\src\main.cpp 39 5 kernel_builder

我不明白运算符怎么会模棱两可,因为函数的签名完全不同。当我完全删除模板,只使用具体的类,以及用命名成员函数替换 operator() 重载时,错误完全相同。

【问题讨论】:

  • 来自不同基类的同名成员函数不会重载。你需要usings。
  • @T.C.该编辑可能会隐藏对 OP 的误解..
  • @dyp 够公平的。我会在评论中指出,overload 的主要模板应该只有一个没有包的参数。
  • @Kietz 解决方法:rextester.com/JPDXKV81915 我猜可能与在尾随返回类型中使用 this 有关。

标签: c++ overloading ambiguous


【解决方案1】:

您需要将基类operator()s 包含在using 中。但是,我不知道如何使用参数包来做到这一点,所以希望其他人可以加入并回答这个问题。

我能做的是重做你的结构,让它一直线性继承,每次重载只需要using下一个:

template <typename... T>
struct overloads
{
    // need this one so that the last overload has 
    // something to "using". If you have an overload for void(),
    // that one will hide this one. If you don't, and call f(),
    // this won't compile... which is fine.
    void operator()();
};

template <typename R, typename... A, typename... T>
struct overloads<R(A...), T...>
: overloads<T...>
{
  typedef std::function<R(A...)> F;
  F f_;

  template <typename... Fs>
  overloads(F f, Fs... fs)
  : overloads<T...>(fs...)
  , f_(f)
  {}

  using overloads<T...>::operator();

  R operator()(A... a)
  {
    return f_(a...);
  }
};

template <typename... T>
struct overloaded_function : public overloads<T...>
{
  overloaded_function(T... t)
  : overloads<T...>(t...)
  { }
};

现在你的f(1.F)f(2, 3) 调用都编译了,因为现在所有的重载都是......可重载的。

【讨论】:

  • “但是,我不知道如何使用参数包来做到这一点,所以希望其他人可以加入并回答这个问题。” 在研究了标准之后,我认为这不是允许包扩展的上下文之一..
  • @dyp - 我想这很好,因为我认为我尝试了所有排列,如果我错过了一个不起眼的... 位置,我会非常沮丧。但除此之外,天哪!
  • 在使用声明时允许包扩展存在一个未解决的问题,所以也许我们会在 C++17 中看到它。此外,我会以不同的方式进行继承:coliru.stacked-crooked.com/a/c71372782285a884
  • @T.C.一个比另一个有什么优势?
  • 大部分情况下不需要尴尬的void operator()();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-12
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多