After having hitten problems with another design, I decided make make a wrapper class to add overloads to a some member functions of the base class if and only if viable overloads do not already exist in the base class. Basically, here is what I am trying to do:
template<typename T>
struct wrapper: T
{
using T::foo;
template<typename Arg>
auto foo(Arg) const
-> std::enable_if_t<not std::is_constructible<Arg>::value, bool>
{
return false;
}
};
struct bar
{
template<typename Arg>
auto foo(Arg) const
-> bool
{
return true;
}
};
In this simple example, wrapper
adds an overloaded foo
only if the one from the base class is not viable (I simplified the std::enable_if
to the simplest possible thing; the original one involved the detection idiom). However, g++ and clang++ disagree. Take the following main
:
int main()
{
assert(wrapper<bar>{}.foo(0));
}
g++ is ok with it: the foo
from wrapper<bar>
is SFINAEd out so it uses the one from bar
instead. On the other hand, clang++ seems to assume that wrapper<bar>::foo
always shadows bar::foo
, even when SFINAEd out. Here is the error message:
main.cpp:30:26: error: no matching member function for call to 'foo' assert(wrapper<bar>{}.foo(0)); ~~~~~~~~~~~~~~~^~~ /usr/include/assert.h:92:5: note: expanded from macro 'assert' ((expr) \ ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/type_traits:2388:44: note: candidate template ignored: disabled by 'enable_if' [with Arg = int] using enable_if_t = typename enable_if<_Cond, _Tp>::type; ^ 1 error generated.
So, who is right? Should this code be rejected just like clang++ does, or should it work and call bar::foo
?