Подтвердить что ты не робот

Правила для неявного преобразования аргументов шаблона

Если вы перегружаете функцию, а затем вызываете ее аргументом, который идеально соответствует одной из перегрузок

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?

У меня создалось впечатление, что неявное преобразование аргументов шаблона было на самом деле более ограничительным, чем неявное преобразование аргументов функции. Есть ли способ обойти эту проблему?

4b9b3361

Ответ 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