ENABLE_IF: случай шаблонного метода шаблонной основы, наследуемой несколько раз

StackOverflow https://stackoverflow.com/questions/7837618

Вопрос

Если у меня есть базовый класс шаблона с методом шаблона:

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;
    }
};

Для примера я упрощаю метод: он должен «существует», только если t == u

Если это класс:

class A : public S<int> {};

Тогда у меня есть то, что я хочу:

int i = 1;
A a;
a.f(i);

компилируется, но

double d = 2.0;
a.f(d);

Не компилируется: ошибка: нет совпадения функции для вызова

Теперь давайте наследуем от S<double> также :

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

Тогда следующий код не компилируется:

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]

Я ожидал, что нет двусмысленности: f<int> существует только для S<int>

В ошибке компилятора мы можем заметить, что T известен, когда этот кусок кода составлен, но не U (u = u).

Любые объяснения или «обходной путь»?

Это было полезно?

Решение

Попробуй это:

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

... или альтернативно ввести функцию в A, например

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

Другие советы

Вы правы, это существует только в S, но два раза. Однажды для каждого типа, int и удваивает. Поэтому в вашем случае вам нужно будет указать, какую именно функцию вы хотите позвонить. Решение от NIM работает так.

Другие дали хорошие обходные пути, но я хочу ответить на этот другой вопрос, который у вас был

Я ожидал, что нет двусмысленности: f<int> существует только для S<int>.

Вы сказали a.f(i) Так что сначала нужно искать имя f в A. Анкет Он находит два fс В S<int> а также S<double>. Анкет Во время поиска имени он еще не знает, что позже он мог выбрать только S<int>::f как победитель, потому что S<double>::f будет выброшен Sfinae. Четкое разделение поиска имени и разрешения перегрузки и вычета аргумента шаблона не допускает такого смешения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top