Antecedentes
Sabemos que el concepto std::same_ases agnóstico al orden (en otras palabras, simétrico): std::same_as<T, U>es equivalente a std::same_as<U, T>( pregunta relacionada ). En esta pregunta, me gustaría implementar algo más general: template <typename ... Types> concept same_are = ...que verifique si los tipos en el paquete Typesson iguales entre sí.
Mi intento
#include <type_traits>
#include <iostream>
#include <concepts>
template <typename T, typename... Others>
concept same_with_others = (... && std::same_as<T, Others>);
template <typename... Types>
concept are_same = (... && same_with_others<Types, Types...>);
template< class T, class U> requires are_same<T, U>
void foo(T a, U b) {
std::cout << "Not integral" << std::endl;
}
// Note the order <U, T> is intentional
template< class T, class U> requires (are_same<U, T> && std::integral<T>)
void foo(T a, U b) {
std::cout << "Integral" << std::endl;
}
int main() {
foo(1, 2);
return 0;
}
(Mi intención aquí es enumerar todos los pares de tipos ordenados posibles en el paquete)
Desafortunadamente, este código no se compilaría , ya que el compilador se queja de que la llamada a foo(int, int)es ambigua. Creo que lo considera are_same<U, T>y are_same<T, U>como no equivalente. Me gustaría saber por qué el código falla y cómo puedo solucionarlo (para que el compilador los trate como equivalentes).
fuente

same_with_othersen cada permutación posible de los tipos.... Typesson iguales? Tal vez std :: conjunción pueda ayudarte. Hay un ejemplo en la parte inferior de la página que parece similar a su enfoque.Respuestas:
El problema es, con este concepto:
Es que la forma normalizada de este concepto es ... exactamente eso. No podemos "desplegar" esto (no hay nada que hacer), y las reglas actuales no se normalizan a través de "partes" de un concepto.
En otras palabras, lo que necesita para que esto funcione es que su concepto se normalice en:
dentro:
Y considere una
&&restricción de expresión de pliegue para subsumir otra restricción de expresión de pliegue&&si su restricción subyacente subsume la restricción subyacente del otro. Si tuviéramos esa regla, eso haría que tu ejemplo funcionara.Es posible agregar esto en el futuro, pero la preocupación en torno a las reglas de subsunción es que no queremos exigir que los compiladores hagan todo lo posible e implementen un solucionador SAT completo para verificar la subsunción de restricciones. Este no parece que lo haga mucho más complicado (realmente solo agregaríamos las reglas
&&y||mediante expresiones de pliegue), pero realmente no tengo idea.Sin embargo, tenga en cuenta que incluso si tuviéramos este tipo de subsunción de expresión doble,
are_same<T, U>aún no subsumiríastd::same_as<T, U>. Solo subsumiríaare_same<U, T>. No estoy seguro de si esto sería posible.fuente
(... && C<T>)no subsumir el conceptoC<T>sorprendería a muchos usuarios.((fold1<Ts> && ...) && (fold2<Ts> &&...))como conjunción de(fold1<Ts> && ...)y(fold2<Ts> && ...)mientras que es atómica.De cppreference.com Restricción_normalización
Entonces
es "atómico"
De hecho,
are_same<U, T>yare_same<T, U>no son equivalentes.No veo cómo implementarlo :-(
fuente