enable_if : how to make it work in the case of templated method of a template base inherited several times

I hope the subject didn't make you run away ;-) Let me be clearer (I'll try at least): If I have a template base class with a template method : template <typename T> class S { public: template <typename U> void f(U p, typename enable_if<is_same<T, U> >::type*dummy = 0) { std::cout << p << std::endl; } }; For the example, I simplify the method : it must "exists" only if T == U If A is this class: class A : public S<int> {}; Then I have what I want: int i = 1; A a; a.f(i); compiles, but double d = 2.0; a.f(d); doesn't compile : error: no matching function for call to ‘A::f(double&)’ It is the expected behavior. Now let's A inherit from S<double> also : class A : public S<int>, public S<double> {}; Then the following code doesn't compile : int i = 1; A a; a.f(i); error: request for member ‘f’ is ambiguous error: candidates are: template<class U> void S::f(U, typename boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T = double] error: template<class U> void S::f(U, typename boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T = int] I expected there is no ambiguity : f<int> exists only for S<int> In the compiler error, we can notice that T is known when this piece of code is compiled, but not U (U = U). Any explanation or "workaround" ? Thanks. Nicolas.

On Thu, Oct 20, 2011 at 10:32 AM, nico <nicolas.guillot@gmail.com> wrote:
template <typename T> class S { public:
template <typename U> void f(U p, typename enable_if<is_same<T, U> >::type*dummy = 0)
First, why are you using enable_if here at all? Is there something wrong with: void f(T p )
Any explanation or "workaround" ?
You need using declarations: class A : public S<int>, public S<double> { public: using S<int>::f; using S<double>::f; }; -- -Matt Calabrese

Matt Calabrese <rivorus@gmail.com> writes:
First, why are you using enable_if here at all? Is there something wrong with: void f(T p )
It could be useful to deny conversions at compile time, with the int/double example being just a demonstration. -- John Wiegley BoostPro Computing, Inc. http://www.boostpro.com

On Thu, Oct 20, 2011 at 7:32 AM, nico <nicolas.guillot@gmail.com> wrote:
I hope the subject didn't make you run away ;-)
Let me be clearer (I'll try at least):
If I have a template base class with a template method :
template <typename T> class S { public:
template <typename U> void f(U p, typename enable_if<is_same<T, U> >::type*dummy = 0) { std::cout << p << std::endl; } };
For the example, I simplify the method : it must "exists" only if T == U
If A is this class:
class A : public S<int> {};
Then I have what I want:
int i = 1; A a; a.f(i);
compiles, but
double d = 2.0; a.f(d);
doesn't compile : error: no matching function for call to ‘A::f(double&)’ It is the expected behavior.
Now let's A inherit from S<double> also :
class A : public S<int>, public S<double> {};
Then the following code doesn't compile : int i = 1; A a; a.f(i); error: request for member ‘f’ is ambiguous error: candidates are: template<class U> void S::f(U, typename boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T = double] error: template<class U> void S::f(U, typename boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T = int]
I expected there is no ambiguity : f<int> exists only for S<int>
In the compiler error, we can notice that T is known when this piece of code is compiled, but not U (U = U).
Any explanation or "workaround" ?
I think a couple using declarations are all you need: ---------------- #include <iostream> #include <boost/type_traits/is_same.hpp> #include <boost/utility/enable_if.hpp> template <typename T> class S { public: template <typename U> void f(U p, typename boost::enable_if<boost::is_same<T, U> >::type*dummy = 0) { std::cout << p << std::endl; } }; class A : public S<int>, public S<double> { public: using S<int>::f; using S<double>::f; }; int main(int argc, const char* argv[]) { int i = 1; A a; a.f(i); return 0; } ---------------- - Jeff
participants (4)
-
Jeffrey Lee Hellrung, Jr.
-
John Wiegley
-
Matt Calabrese
-
nico