Wiadomość błędu przy niespełnieniu warunku requires

1

Hej.
Chciałbym dodać wiadomość błędu w przypadku, gdy warunek requires nie będzie spełniony - coś jak static_cast robi.

Na przykład mam taki kod:

template<typename T>
concept Nameable = requires() 
{
    T::NAME;
};

struct WithName
{
    static constexpr const auto NAME = "testName";
};
struct WithoutName
{
};

////////////////////////////////////
template<class T>
requires Nameable<T>
class ErrorIfNotNameable
{
public:
    ErrorIfNotNameable()
    {
        cout << "ErrorIfNotNameable(nameable)" << endl;
    }
};

int main()
{
    ErrorIfNotNameable<WithName>{};
    //ErrorIfNotNameable<WithoutName>{}; /// Error
    return 0;
}

Ten fragment kodu działa tak jak tego oczekuję, czyli nie można stworzyć obiektu klasy ErrorIfNotNameable podając mu argument, który nie jest Nameable.
Ja dodatkowo chciałbym wyświetlić konkretną wiadomość błędu np. "Sorry, ale musisz podać Name, bo <powód>".

Jakieś pomysły?

2

Słówko kluczowe requires załatwia sprawę na etapie kompilacji, natomiast wyświetlenie wiadomości następowałoby już w czasie życia programu (w runtimie).
Więc jeśli chciałbyś dla nieprawidłowego typu wyświetlić własną wiadomość w oparciu o std::cout lub podobne, to raczej byłoby to niemożliwe jeśli opierasz się o requires.
Myślę, że wyświetlenie własnej wiadomości błędu byłoby możliwe z assert, ale wtedy nie używałbyś requires, którego chcesz przecież użyć.

Dodatkowo: nie widzę niestety nigdzie w dokumentacji wzmianki o dodawaniu własnego ciągu znaków wyświetlanego w przypadku niespełnionego warunku.
Na Twoim przykładzie kodu próbowałem z użyciem parametrów do requires( std::string customMessage ) ale to bez sensu, chyba, że ktoś znajdzie sposób.


Warto zaznaczyć:
Nie potrzebujesz const gdy masz constexpr.
Sprawdź:

struct WithName
{
    static constexpr auto NAME = "testName";
};

    auto nameable = WithName();
    nameable.NAME = "new name"; // expression must be a modifiable lvalue
1

Znalazłem rozwiązanie.

static_assert(Nameable<T>, "My message");
0

@Bartosz36: w runtime możesz zrobić tak:

template<typename T>
void foo(T bar)
{
       std::cout << "non nameable" << '\n';
}

template <typename T>
requires Nameable<T>
void foo (T bar)
{
   std::cout << bar.NAME << '\n';
}

https://godbolt.org/z/T3qsdY

1 użytkowników online, w tym zalogowanych: 0, gości: 1