c++functionc++20autoambiguity

C++ auto templated function overload ambiguity


#include <iostream>
#include <concepts>


struct Sound { int amplitude; };
struct Light { int brightness; };

template <typename T>
concept Alert = std::derived_from<T, Sound> && std::derived_from<T, Light>;


struct FirstSound : Sound{};
struct FirstLight : Light{};
struct FirstSoundLight : FirstSound, FirstLight{};

struct LastSound : Sound{};
struct LastLight : Light{};
struct LastSoundLight : LastSound, LastLight{};

template <typename T>
concept FirstAlert = std::derived_from<T, FirstSound> && std::derived_from<T, FirstLight>;

template <typename T>
concept LastAlert = std::derived_from<T, LastSound> && std::derived_from<T, LastLight>;


void warn(FirstAlert auto const& a, LastAlert auto const& b)
{ std::cout << "Special warning"; }

void warn(Alert auto const& a, LastAlert auto const& b) = delete;
//{ std::cout << "Deleted warning"; }

void warn(Alert auto const& a, Alert auto const& b)
{ std::cout << "General warning"; }

int main() 
{
    warn(FirstSoundLight{}, LastSoundLight{});
    return 0;
}

The code above is a simplified version of my problem. How can I make the compiler select functions unambigiously in the given order without explicitly casting the parameters?


Solution

  • You need to subsume concept Alert in your 2 other concepts:

    template <typename T>
    concept FirstAlert = Alert<T> && std::derived_from<T, FirstSound> && std::derived_from<T, FirstLight>;
    
    template <typename T>
    concept LastAlert = Alert<T> && std::derived_from<T, LastSound> && std::derived_from<T, LastLight>;