Consider this code:
#include <utility>
int foo_i(int x) { return x + 1; }
char foo_c(char x) { return x + 1; }
using II = int (*)(int);
using CC = char (*)(char);
template<typename F>
struct fn {
F f;
template<typename... Args>
decltype(auto) operator()(Args&&... args) const
{
return f(std::forward<Args>(args)...);
}
};
struct fn_2 : private fn<II>, private fn<CC> {
fn_2(II fp1, CC fp2)
: fn<II>{fp1}
, fn<CC>{fp2}
{}
using fn<II>::operator();
using fn<CC>::operator();
};
int main()
{
fn_2 f(foo_i, foo_c);
f(42);
}
In principle, it fn<T>stores a functor (not necessarily a function pointer) of the type T, and its variational operator()translates everything into a functor.
This code compiles with gcc 4.9.2 through gcc 6.1 , but is rejected by every version of clang I tried, even clang 3.8 . clang complains that the call is ambiguous. (I would appreciate it if someone tries to compile it with VS, because I don't have access to it right now.)
Which compiler is right, and how can I get around this mismatch?
: , () , : fn<T> operator(). (, -... .:/) :
template<typename F>
struct fn : private F {
using F::operator();
};
template<typename R, typename... Args>
struct fn<R (*)(Args...)> {
fn(R (*f)(Args...)) noexcept : f_(f) {}
R operator()(Args&&... args) const
{
return f_(std::forward<Args>(args)...);
}
private:
R (*f_)(Args...);
};