Boost logo

Boost :

Subject: Re: [boost] enable_if : how to make it work in the case of templated method of a template base inherited several times
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2011-10-20 10:55:15


On Thu, Oct 20, 2011 at 7:32 AM, nico <nicolas.guillot_at_[hidden]> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk