overload
構造体と同じコードをここに書くと、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()
1をインポートするために作るの標準的な解釈にはいくつかの問題があります
#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;
}
これ以下に再現コードhttps://wandbox.org/permlink/5Z2jsEjOewkGoPeXされています一つ。しかし、どういうわけかOverloadFuncImpl
の機能特殊化のoperator()
は、using
で正しくインポートされていないようです。
上記のコードは、OverloadFuncImpl
を使用しない場合、またはOverloadFuncImpl
という機能の部分的な特殊化を除外した場合に問題ありません。
私はすでにこのコードを回避策で使用していますが、なぜ上記のコードが機能しないのか不思議です。私はそれを把握していないようだ...私はすべての基本クラスのoperator()
すべてをインポートしたときにそれはなぜですか?依然としてあいまいな過負荷問題がありますか?
私は、効果的に問題に設定過負荷で関連する候補者は
呼ばchar operator()(char);
double operator()(double) const;
ある
Btw、これはあなたの質問に直接関係しませんが、関数ポインタの実装にはさらに問題があります。右辺値参照をとる関数ポインタから過負荷を作成してみてください。 –
@NirFriedmanあなたはどの部分について話していますか?コンストラクタまたは呼び出し演算子? – Curious
コールオペレータ。 http://coliru.stacked-crooked.com/a/2d3469ea05c357c1 –