c++ метапрограммирование - Почему возникает ошибка при вызове функции-члена шаблона с явным параметром типа?




что tmp (2)

Я не понимаю, мне кажется, что вызов f полностью однозначен, но он не может скомпилировать expected primary-expression before 'int' . Если я прокомментирую строку с вызовом f , она компилируется отлично.

template<typename T>
struct A {
    template<typename S>
    void f() { }
};

template<typename T>
struct B : A<T> {
    void g() {
        this->f<int>();
    }
};

Answers

Это связано с действительно неясным предоставлением стандарта, в котором, если у вас есть шаблон, который пытается получить доступ к функции шаблона в объекте, тип которого зависит от аргумента шаблона, вы должны использовать ключевое слово template странным образом:

this->template f<int>();

Это похоже на странность с typename которая возникает с зависимыми типами, кроме как применительно к функциям. В частности, если вы не template ключевое слово template , существует разбор синтаксической разницы между

this->f<int>()

(что вы намеревались), и

((this->f) < int) > ()

что не имеет смысла (отсюда и ваша ошибка). Использование template ключевого слова здесь устраняет неоднозначность и заставляет компилятор признать, что он смотрит на вполне действительный вызов шаблонной функции-члена, а не на искаженную массу символов.

Надеюсь это поможет!


Правила разрешения перегрузки определяют только частичный порядок в наборе всех совпадений - если перегрузка F1 не лучше, чем F2 , это не означает, что F2 лучше, чем F1 . Точный частичный порядок можно рассматривать как сравнение двух точек в k размерах, где число аргументов k . Давайте определим этот частичный порядок в точках в пространстве k -dim - (x_1, x_2,..., x_k) < (y_1, y_2,..., y_k) if x_i <= y_i for all i and x_j < y_j for at least one j . Это точно частичный порядок для кандидатов, не являющихся шаблонами, определенных стандартом.

Давайте посмотрим на ваши примеры:

void func(double, int,    int,    double) {}
                  vvv     vvv       vvv
                 better  better    equal
void func(int,    double, double, double) {}
          vvv                       vvv
         better                    equal

Таким образом, ни перегрузка не лучше, чем другая.

Во втором примере:

void func(int,   int,   int,   double) {}
          vvv    vvv    vvv     vvv
         equal  better better  equal
void func(int, double, double, double) {}
          vvv
         equal

Теперь первая перегрузка лучше второй во всех, кроме одного аргумента И никогда не хуже второй. Таким образом, нет никакой двусмысленности - частичный порядок действительно объявляет первое лучше.

(В приведенном выше описании не рассматриваются шаблоны функций. Более подробную информацию вы можете найти на странице cppreference .)





c++ templates metaprogramming