Как применить стиль ко всем дочерним элементам

Основная причина этой (стандартно-согласованной) двусмысленности, по-видимому, лежит в стоимости преобразования: разрешение перегрузки пытается минимизировать операции, выполняемые для преобразования аргумента в соответствующий параметр. Массив эффективно указатель на свой первый элемент, хотя и украшен некоторой информацией типа времени компиляции. Преобразование от массива к указателю не стоит больше, чем, например, сохраняя адрес самого массива или инициализируя ссылку на него. С этой точки зрения двусмысленность кажется оправданной, хотя концептуально она неинтуитивная (и может быть подпара). Фактически, эта аргументация применяется ко всем преобразованиям Lvalue, как это предлагается в приведенной ниже цитате. Другой пример:

void g() {}

void f(void(*)()) {}
void f(void(&)()) {}

int main() {
    f(g); // Ambiguous
}

Следующее обязательное стандартное. Функции, которые не являются специализациями какого-либо шаблона функции, предпочтительнее, чем те, которые являются, если обе они одинаково хорошо соответствуют (см. [Over.match.best] / (1.3), (1.6)). В нашем случае преобразование выполняется преобразованием между массивами и указателями, которое является преобразованием Lvalue с рангом Точного соответствия (согласно таблице 12 в [over.ics.user]). [over.ics.rank] / 3:

  • Стандартная последовательность преобразования S1 является лучшей последовательностью преобразования, чем стандартная последовательность преобразования S2, если S1 является правильной подпоследовательностью S2 (сравнение последовательностей преобразования в канонической форме, определенных в 13.3.3.1.1, за исключением любого преобразования Lvalue, последовательность преобразования идентичности рассматривается как подпоследовательность любой последовательности, не являющейся идентификационной конверсией), или, если не это, ранг S1 лучше ранга S2 или S1 и S2 имеют один и тот же ранг и различимы по правилам в параграфе ниже, или, если не это, [..]
blockquote>

Первая маркерная точка исключает наше преобразование (поскольку это преобразование Lvalue). Второй требует разницы в рангах, которых нет, так как оба преобразования имеют Точный рейтинг соответствия; «Правила в нижеследующем абзаце», т. Е. В [over.ics.rank] / 4, также не охватывают преобразования между массивами и указателями. Итак, верьте или нет, ни одна из обеих последовательностей преобразования не лучше, чем другая, и, следовательно, выбрано char const* -overload.


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

template 
auto foo(T s)
  -> std::enable_if_t{}>
{
    std::cout << "raw, size=" << std::strlen(s) << std::endl;
}

Демо .

75
задан Mowzer 17 October 2017 в 23:58
поделиться