函数基类的不明确重载

时间:2017-08-30 03:44:50

标签: c++ templates c++14 overloading template-specialization

我试图在overload这里编写与#include <utility> #include <type_traits> #include <cassert> #include <string> namespace { template <typename Func> class OverloadFuncImpl : public Func { public: template <typename F> explicit OverloadFuncImpl(F&& f) : Func{std::forward<F>(f)} {} using Func::operator(); }; template <typename ReturnType, typename... Args> class OverloadFuncImpl<ReturnType (*) (Args...)> { public: template <typename F> explicit OverloadFuncImpl(F&& f) : func{std::forward<F>(f)} {} ReturnType operator()(Args... args) { return this->func(args...); } private: ReturnType (*func) (Args...); }; template <typename... Funcs> class Overload; template <typename Func, typename... Funcs> class Overload<Func, Funcs...> : public OverloadFuncImpl<Func>, public Overload<Funcs...> { public: template <typename F, typename... Fs> explicit Overload(F&& f, Fs&&... fs) : OverloadFuncImpl<Func>{std::forward<F>(f)}, Overload<Funcs...>{std::forward<Fs>(fs)...} {} using OverloadFuncImpl<Func>::operator(); using Overload<Funcs...>::operator(); }; template <typename Func> class Overload<Func> : public OverloadFuncImpl<Func> { public: template <typename F> explicit Overload(F&& f) : OverloadFuncImpl<Func>{std::forward<F>(f)} {} using OverloadFuncImpl<Func>::operator(); }; } template <typename... Funcs> auto make_overload(Funcs&&... funcs) { return Overload<std::decay_t<Funcs>...>{std::forward<Funcs>(funcs)...}; } char foo(char ch) { return ch; } int main() { auto overloaded = make_overload( [&](int integer) { return integer; }, [&](std::string str) { return str; }, [&](double d) { return d; }, foo); assert(overloaded("something") == "something"); assert(overloaded(1.1) == 1.1); return 0; } 结构相同的代码,并将其扩展为使用函数。

以下是

下面的代码http://en.cppreference.com/w/cpp/utility/variant/visit
In file included from /opt/wandbox/gcc-7.2.0/include/c++/7.2.0/cassert:44:0,
                 from prog.cc:3:
prog.cc: In function 'int main()':
prog.cc:66:26: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
     assert(overloaded(1.1) == 1.1);
                          ^
prog.cc:62:21: note: candidate 1: main()::<lambda(double)>
         [&](double d) { return d; },
                     ^
prog.cc:19:20: note: candidate 2: ReturnType {anonymous}::OverloadFuncImpl<ReturnType (*)(Args ...)>::operator()(Args ...) [with ReturnType = char; Args = {char}]
         ReturnType operator()(Args... args) {
                    ^~~~~~~~

这是我得到的错误

operator()

编译器和标准解释存在一些问题,需要逐个导入operator()。但不知怎的,OverloadFuncImpl的函数专精的using似乎无法通过OverloadFuncImpl正确导入。

请注意,当我不使用OverloadFuncImpl或排除operator()的功能部分特化时,上面的代码就可以了。

我已经让这段代码使用了解决方法,但我只是想知道为什么上面的代码不起作用。我似乎无法弄明白......当我导入所有基类的所有reyclerView时,为什么呢?仍存在模糊的过载问题?

我尝试在较小的上下文中重现错误,但无法...

1 个答案:

答案 0 :(得分:5)

    ReturnType operator()(Args... args) const {
//                                      ^^^^^
        return this->func(args...);
    }

有效地解决了过载问题中的相关候选人

 char operator()(char);
 double operator()(double) const;

调用非const对象,其参数类型为double

隐式对象参数的第一个胜利;第二个赢得实际的函数参数。随之而来的是歧义。