Каков эквивалент броска для понятий?
Рассмотрим a class A
, удовлетворяющий двум понятиям ConceptA
и ConceptB
. Пусть функция foo
перегружена для двух понятий:
void foo(ConceptA& arg);
void foo(ConceptB& arg);
A a;
fun(concept_cast<ConceptA>(a));
Примечание. В этом примере используется синтаксис "Тесная нотация", предложенный как часть N3701, §5
Есть ли что-то вроде concept_cast
, которое позволяет пользователям выбирать перегрузку?
Например:
Давайте скажем
ConceptA
говорит, что T должна иметь функцию-член bar()
ConceptB
говорит, что T должна иметь функцию-член baz()
и class A
имеет как bar()
, так и baz()
функцию-член
Его явно двусмысленный, но есть ли способ явно выбрать, как мы имеем static_cast
для нормальных перегрузок?
Обновить. Принятый ответ более 2 лет. Любое обновление в С++ 17?
Ответы
Ответ 1
Если одно из понятий представляет собой более ограниченную версию другого (например, все, что удовлетворяет ConceptA
, также будет удовлетворять ConceptB
, но не наоборот), то наиболее ограничиваемая перегрузка, удовлетворяющая A
, будет выбраны.
Если ни одна из этих концепций не является более ограниченной, чем другая, то две из них считаются неоднозначными перегрузками. Учитывая, как вы сформулировали вопрос, я ожидаю, что вы уже это знали.
Что касается concept_cast
, я не думаю, что в текущем предложении есть что-то подобное. По крайней мере, не о встрече Бристоля (13 апреля). Я не ожидаю, что это изменится, поскольку в настоящее время основное внимание, по-видимому, заключается в том, чтобы убедиться в том, что ядро предложения концепций-lite/constraints является приемлемым и приемлемым для комитета.
Вероятно, будет определенная потребность в явном выборе перегруженных функций шаблона, подобных этому, и, возможно, такой перевод правильных вещей, но я не уверен. Учтите, что такой приведение будет полезно только для значений перегрузки, где static_cast
является более общей функцией. Результат concept_cast
будет таким же, как исходное значение вне контекста разрешения перегрузки!
Изменить: Рассматривая последнее предложение (N3701), не предусмотрено явно указывать, какой шаблон для создания экземпляра.
Ответ 2
Ваше утверждение о том, что static_cast
может быть использовано для явного выбора "нормальной" перегрузки, является просто сообразительным. В настоящее время на С++ можно написать следующее:
template<typename P, EnableIf<NullablePointer<P>>...>
void foo(P&);
template<typename It, EnableIf<Iterator<It>>...>
void foo(It&);
Предполагая, что NullablePointer
и Iterator
выполняют проверку концепций для связанных Стандартных понятий, тогда int* q; foo(q);
не имеет надежды на компиляцию, потому что int*
является одновременно моделью NullablePointer
и Iterator
(и ни одна из них концепция включает другое). Нет ничего очевидного для static_cast
, чтобы помочь в этой ситуации.
Мой пример (который вы можете проверить для себя) чрезвычайно важен, потому что этот код является тем, что Concepts Lite пытается формализовать. Набор перегрузки, который вы представляете, эквивалентен:
template<typename A>
requires ConceptA<A>
void foo(A& arg);
template<typename B>
requires ConceptB<B>
void foo(B& arg);
Обратите внимание на сходство между предложениями requires
и предложениями EnableIf
.