Почему компилятор не может определить значение моего шаблона из аргумента функции?

Следующее не будет компилироваться:

enum E {A,B,C};
template<E m>
void foo(E m) {}

int main() {
foo(A);
return 0;
}

Я получаю следующие ошибки:

  • объявление ‘E m’: void foo (E m) {}: шаблон теней parm ‘E m’
  • ошибка: нет подходящей функции для вызова ‘foo (E)’:
    Foo (А);
  • кандидат: шаблон void foo (E): void foo (E m) {}
  • Сбой вывода / замены аргумента шаблона: невозможно вывести параметр шаблона ‘m’: foo (A);

Я не понимаю, что именно здесь не так. Почему компилятор не может определить параметр шаблона из аргумента функции?

Что мне нужно сделать, чтобы сделать эту работу?

2

Решение

Если вы хотите аргумент во время выполнения, используйте:

void foo(E m) {}

Который имеет значение m типа E, (примечание: нет template<E m> требуется)

Если вам нужен аргумент времени компиляции, используйте:

template<E m>
void foo() {}

и позвоните:

foo<A>();

Или если вы хотите foo работать для всех типов перечисления:

template<typename E>
void foo(E m) {}

И, возможно, проверьте перечисления с

static_assert(std::is_enum<E>::value, "E is not an enumeration");

в теле функции. (Вы также можете использовать SFINAE для удаления foo из набора перегрузки, если нужно, спросите, нужна ли вам помощь с этим)


Обновление: объяснение вашего исходного кода и что с ним не так:

template<E m> void foo(E m) {}
//       ^^^ (1)       ^^^ (2)

(1) — аргумент времени компиляции m типа E(2) — аргумент времени выполнения также называется m а также типа E, Поскольку оно имеет то же имя, второй аргумент скрывает первый. Используя имя m в вашей функции будет доступ только ко второму аргументу, а вы не сможете получить доступ к первому. Теперь рассмотрим:

template<E m1> void foo(E m2) {}

Теперь вы можете получить доступ к аргументам под разными именами, т.е. m1 а также m2, Если вы вызываете функцию следующим образом:

foo<A>(B);

затем m1 является A а также m2 является B, И все же оба имеют одинаковый фиксированный тип E, Они являются независимыми параметрами, и значение параметра времени выполнения не будет использоваться для параметра времени компиляции.

В зависимости от того, какой тип или аргумент вам нужен (время компиляции или время выполнения), вы просто пропускаете тот, который вам не нужен, и в итоге получаете одну из вышеуказанных реализаций.

Мне не на 100% ясно, где твоя настоящая проблема, что не является нетипичным для начинающих, так как, по общему признанию, трудно описать проблему, которую ты не понимаешь на самом деле, но не забывай начинать с понимания разницы между временем компиляции и параметры времени выполнения и как они могут быть использованы.

5

Другие решения

Я думаю, вы хотели написать:

enum E {A,B,C};
template<typename T>
void foo(T m) {}

int main() {
foo(A);
return 0;
}
2

Наконец меня осенило, почему это не компилируется. Хотя в моем конкретном случае аргумент функции является константой времени компиляции (член enum), в общем случае аргумент функции зависит от времени выполнения. Значение шаблона должно быть константой времени компиляции, поэтому значения аргументов функции недопустимы для вывода значения шаблона. Если механизм для принудительного применения этого скрывает имена, то я думаю, что это случайно.
Вывод состоит в том, что, хотя шаблонные типы функций могут быть выведены из типа аргумента функции, значения шаблонов не выводятся.

0