C++ Logo

std-proposals

Advanced search

Re: [std-proposals] attribute [[unevaluated]]

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Tue, 20 May 2025 13:07:19 +0100
On Tue, May 20, 2025 at 9:02 AM Jonathan Wakely wrote:
>
>
> If the function body is empty then it can typically be a variable template or an alias template.
> Or have no function body at all. You don't need to define it if you're not calling it.


I didn't realise that my previous code would compile and link
successfully without a body, that's cool.

But then there's times when a body is needed, like in the following
function. (Note in places that I had to use *((A*)nullptr) instead of
'declval' because the compiler refused to compile it). You can
dereference a null pointer in a non-evaluated context, it's fine.

    #include <type_traits> // is_same, remove_cvref
    #include <utility> // declval

    template<class ExcludedTypezzz, class Azzz, class Bzzz, class Czzz>
    consteval decltype(auto) GetType(Azzz&&, Bzzz&&, Czzz&&) noexcept
    {
        using std::declval, std::is_same_v, std::remove_cvref_t;

        typedef remove_cvref_t<Azzz> A;
        typedef remove_cvref_t<Bzzz> B;
        typedef remove_cvref_t<Czzz> C;
        typedef remove_cvref_t<ExcludedTypezzz> ExcludedType;

        constexpr auto is_valid = []<typename ExcludedType2, typename
T>(void) consteval noexcept -> bool
        {
            if constexpr ( !requires { declval<typename
T::value_type2>(); } ) return false;
            else if constexpr ( is_same_v< typename T::value_type2,
void > ) return false;
            else if constexpr ( is_same_v< typename T::value_type2,
ExcludedType > ) return false;
            else return true;
        };

        if constexpr ( is_valid.template
operator()<ExcludedType,A>() ) return *(A*)nullptr;
        else if constexpr ( is_valid.template
operator()<ExcludedType,B>() ) return *(B*)nullptr;
        else if constexpr ( is_valid.template
operator()<ExcludedType,C>() ) return *(C*)nullptr;
        else if constexpr ( requires { declval<A&>().begin(); } ) {
return ((A*)nullptr)->begin(); }
        else if constexpr ( requires { declval<B&>().begin(); } ) {
return ((B*)nullptr)->begin(); }
        else if constexpr ( requires { declval<C&>().begin(); } ) {
return ((C*)nullptr)->begin(); }
        else
        {
            static_assert(false, "Wrong types!");
        }
    }

    #include <sstream> // ostringstream
    #include <string> // string
    #include <vector> // vector

    #include <iostream> // cout

    int main(void)
    {
        std::ostringstream ss;
        std::string s;
        std::vector<int> vec;

        typedef decltype(GetType<int>(ss,s,vec)) SomeType;

        std::cout << "Hi\n";
    }

The above program compiles and runs fine.

Received on 2025-05-20 12:07:32