#c #c 20
#c #c 20
Вопрос:
Как следует из названия, я хочу foo
принимать int
type только в качестве 2-го параметра.
#include <iostream>
#include <concepts>
#include <type_traits>
template <typename U, typename T> concept IS_INT =
requires (U u, T t) {
{ t 0 } -> std::same_as<int>;
};
IS_INT {U, T}
void foo (U u, T t)
{
std::cout << "IS INT!" << std::endl;
return;
}
int main()
{
foo(1, 1);
return 0;
}
Он работает, но g (версия 10.2.0) генерирует это предупреждение
test.cpp:11:8: warning: template-introductions are not part of C 20 concepts [-fconcepts-ts]
11 | IS_INT {U, T}
| ~~~~~~~^~~~~~
Альтернативный способ записи IS_INT {U, T}
? чтобы избавиться от этого предупреждения?
Наконец, как переписать это ограничение (t равно int) без необходимости добавлять 0?
{ t 0 } -> std::same_as<int>;
Редактировать:
template <typename U, typename T> concept IS_INT =
requires (U u, T t) {
std::same_as<T, int>;
};
Не выдает ошибку компиляции для
foo(1, "TTT");
Комментарии:
1.
IS_INT {U, T}
Что это за синтаксис?{ t 0 }
Вы хотите, чтобы повышенный тип былint
или тип былint
?2. @KamilCuk en.cppreference.com/w/cpp/experimental/constraints
3. Тогда вы хотите
std::same_as<T, int>
, чтобы неt 0
былоint
.оператор будет продвигать свои операнды.
4. @KamilCuk да, но если я изменю тело
{ t 0 } -> std::same_as<int>;
наstd::same_as<T, int>;
in main дляfoo(1, "TTT")
, я не получу ошибку компиляции. Я предполагаю, что я злоупотребляю понятиями…
Ответ №1:
Вы можете сохранить двоичную форму даже в текущей версии core concepts:
template <typename U, typename T> concept IS_INT =
requires (U u, T t) {
{ t 0 } -> std::same_as<int>;
};
template<class T, IS_INT<T> U>
void foo (U u, T t)
{
std::cout << "IS INT!" << std::endl;
return;
}
(обратите внимание на обратный порядок параметров: как правило, если концепция принимает несколько параметров, то только первый из них является особенным, а U стоит первым в вашем определении). Полный TS-сахар, как предупреждает g , в настоящее время не является стандартным.
Наконец, как переписать это ограничение (t равно int) без необходимости добавлять 0?
template<class T, class U> concept is_int = std::same_as<T, int>;
?
Комментарии:
1. О, переход
{ t 0 } -> std::same_as<int>;
наstd::same_as<T, int>;
этот простой … иtemplate<class T, IS_INT<T> U>
это то, что мне было нужно. Спасибо!2. Я только что заметил, изменив
{ t 0 } -> std::same_as<int>;
наstd::same_as<T, int>;
will not выдаст ошибку, вfoo(1, "TTT")
то{ t 0 } -> std::same_as<int>;
время как does . Я что-то упускаю?3. @TonyTannous да. Одно из них — это вложенное требование, которое должно быть выполнено, другое — всего лишь одно выражение, которое компилируется в любом случае и на самом деле ничего не ограничивает.
Ответ №2:
Как следует из названия, я хочу, чтобы foo принимал только
int
type в качестве своего 2-го параметра.
Это требует унарной концепции — вы хотите ограничить 2-й параметр, сам по себе, быть int
. Это проверка требования одного типа.
Это:
template <typename U, typename T> concept IS_INT =
является двоичным понятием (независимо от того, что следует за =
). Это ограничивает два разных типа, T
и U
, в некотором роде. Независимо от того, что вы пишете после этого, на самом деле это не касается вашего варианта использования.
Вы хотите сказать, что тип — это an int
. То есть:
template <typename T> concept is_int = std::is_same_v<T, int>;
Который вы можете использовать, таким образом:
template <typename U, is_int T>
void foo (U u, T t);
Это не имеет ограничений на первый параметр, а второй параметр должен иметь тип int
.
Теперь стандартная библиотека фактически поставляется с концепцией именно для этой проблемы. Он называется same_as
:
template <typename U, std::same_as<int> T>
void foo (U u, T t);
Кроме того, стоит отметить требование:
{ t 0 } -> std::same_as<int>;
На самом деле не требует t
наличия типа int
. Это справедливо и для любого целочисленного типа, приведенного ниже int
, из-за целочисленного продвижения.
Комментарии:
1. Спасибо за ответ (уже 1) Наверное, я не понимаю, когда использовать требования и накладывать ограничения в
{}
блоке. Еще раз спасибо.