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" ?

有帮助吗?

解决方案

Try this:

a.S<int>::f(i);

...or alternatively inject the function into A, e.g.

class A : public S<int>, public S<double> 
{
public:
  using S<int>::f;
  using S<double>::f;
};

其他提示

You are right it only exists in S, but two times. Once for each type, int and double. So in your case you will need to specify exactly which function you want to call. The solution from Nim works just like that.

Others have given good workarounds, but I want to answer that other question you had

I expected there is no ambiguity : f<int> exists only for S<int>.

You said a.f(i) so it first needs to look for name f in A. It finds two fs. In S<int> and S<double>. At name lookup time, it does not know yet that it later could have only selected S<int>::f as a winner because S<double>::f would be thrown away by SFINAE. The clear separation of name lookup and overload resolution and template argument deduction does not allow such intermingling.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top