Estou aprendendo sobre requisitos aninhados em conceitos c++. Considere o trecho de código abaixo:
#include <concepts>
#include <iostream>
// Nested requirement
template <typename... Ts>
concept VariadicAddable = requires(Ts... vs)
{
(... + vs); // + operator is provided
requires sizeof...(Ts) > 1; // Atleast two arguments are provided
};
template <VariadicAddable... Ts>
auto add_variadic(Ts... vs)
{
return (... + vs);
}
int main()
{
std::cout << add_variadic(1, 2) << std::endl; // Expecting no failure here
//std::cout << add_variadic(1) << std::endl; // Expecting failure here
}
Estou recebendo erros ao compilar isso... (Godbolt, msvc vs17.10 com opção c++20)
<source>(20): error C2672: 'add_variadic': no matching overloaded function found
<source>(13): note: could be 'auto add_variadic(Ts...)'
<source>(20): note: the associated constraints are not satisfied
<source>(12): note: the constraint was not satisfied
Também tentei uma variação de especificação da mesma restrição, como abaixo:
template <typename... Ts>
concept VariadicAddable = (sizeof...(Ts) > 1) && requires(Ts... vs)
{
(... + vs); // + operator is provided
};
Estou recebendo erro semelhante nesse caso também. Alguém tem ideia do que estou perdendo?
O problema é que
concept
os parâmetros de tipo de modelo precedentes devem restringir um único tipo, em vez do relacionamento entre vários parâmetros de tipo. O seuconcept
em si está bom, mas não pode ser usado da maneira que você mostrou.Tentei compilar com clang e recebi uma mensagem de erro um pouco mais clara:
É claro que cada um
int
é verificado para o conceitoVariadicAddable
individualmente, em vez de ter o pacote inteiro passado para o conceito. Parasizeof...(Ts)
ser maior que 1 (digamos que seja 2), o conceito antes do parâmetro de modelo precisaria estar no formato deVariadicAddable<T>
para algum tipoT
, em vez de apenasVariadicAddable
, mas essa claramente não é sua intenção.A solução é simples: basta usar o conceito na
requires
cláusula.