Правила для неявного преобразования аргументов шаблона
Если вы перегружаете функцию, а затем вызываете ее аргументом, который идеально соответствует одной из перегрузок
int f(int){return 3;}
int f(bool){return 4;}
... //inside main()
f(1); //Calls f(int)
компилятор просто выбирает это (идеальное) соответствие перед попыткой каких-либо неявных преобразований. Однако я пытаюсь перегрузить функцию tempĺate, как в
template <bool veracity>
int f(){return 1;}
template <int amount>
int f(){return 2;}
... //inside main()
f<1>();
но компилятор продолжает жаловаться на неоднозначный вызов перегруженного f(), заявив, что он может быть либо f<true>()
, либо f<1>()
. Разве компилятор просто не выбирает идеальное совпадение, а не пытается преобразовать 1 в true?
У меня создалось впечатление, что неявное преобразование аргументов шаблона было на самом деле более ограничительным, чем неявное преобразование аргументов функции. Есть ли способ обойти эту проблему?
Ответы
Ответ 1
Аргумент, который вы поставляете, не является типом, это значение, поэтому правила немного разные - вам нужно применить правила для аргументов, отличных от типа. Для аргументов, отличных от типа, допускаются неявные преобразования. §14.3.2/5:
Следующие преобразования выполняются для каждого выражения, используемого в качестве шаблона-аргумента типа non-type. Если не-тип шаблона-аргумента не может быть преобразован в тип соответствующего шаблона-параметра, тогда программа плохо сформирована.
- для шаблона-шаблона непигового типа интегрального или перечисляемого применяются преобразования, разрешенные в преобразованном постоянном выражении (5.19).
В С++ 03 формулировка незначительно отличается, но эффект по существу идентичен (также §14.3.2/5):
- для непикового шаблона-параметра интегрального или перечисляющего типа применяются интегральные поощрения (4.5) и интегральные преобразования (4.7).
В любом случае, поскольку 1
является и int
и неявно конвертируется в bool
, ваш вызов неоднозначен.
Ответ 2
Поскольку это не ошибка компилятора, а функция языка (см. этот ответ), вам нужно найти работу.
Либо вы должны переименовать свои функции, либо можете использовать этот хак:
template <typename T> struct F;
template<> struct F<bool> {
template <bool veracity>
static int f(){return 1;}
};
template<> struct F<int> {
template <int amount>
static int f(){return 2;}
};
template <typename T, T value>
int f() { return F<T>::template f<value>(); }
// inside main():
std::cout << f<int, 2>() << '\n'; // prints 2
std::cout << f<bool, 2>() << '\n'; // prints 1