0

I want to check if a shared_ptr is uninitialized, i.e. if it is a nullptr or if it has a default value (as would be the case if created by using std::make_shared). For this purpose I wrote a code to check if the shared pointer is having a default constructed value of a class/struct. To achieve this, I also need to know if a class/struct defines the operator== and to figure that out I have has_equate. The code to check if a shared pointer is uninitialized is:

template<class L, class R = L>
concept has_equate = requires(const L & lhs, const R & rhs)
{
    { lhs == rhs } -> std::same_as<bool>;
};

template <typename T>
bool isSharedPtrUninitialized(const std::shared_ptr<T>& shared)
{
    if(shared) {
        if(has_equate<T>) {
            T tmp;
            if(*shared == tmp)
                return true;
        }
        return false;
    }
    return true;
}

If I don't define operator== for my class/struct the above line of code gives the following error:

Error C2678 binary '==': no operator found which takes a left-hand operand of type 'T' (or there is no acceptable conversion)

Since I am checking if the operator== exists or not for the class/struct by using has_equate before proceeding to check if the given shared pointer has a default constructed value, I would like to suppress this error for this particular line of code.

What I have tried so far:

template <typename T>
bool isSharedPtrUninitialized(const std::shared_ptr<T>& shared)
{
    if(shared) {
        if(has_equate<T>) {
            T tmp;
            #pragma warning(suppress: 2678)
            if(*shared == tmp)
                return true;
        }
        return false;
    }
    return true;
}
#pragma warning(push)
#pragma warning(disable: 2678)
template <typename T>
bool isSharedPtrUninitialized(const std::shared_ptr<T>& shared)
{
    if(shared) {
        if(has_equate<T>) {
            T tmp;
            if(*shared == tmp)
                return true;
        }
        return false;
    }
    return true;
}
#pragma warning(pop)

None of it is working (I assume it is because C2678 is an error and not a warning). Is there a way I could suppress this error for just if(*shared == tmp) line of code or just for the isSharedPtrUninitialized function as I do not want to do this for the entire thing.

Chaitanya
  • 177
  • 2
  • 9
  • 4
    If the compiler thinks it’s an error there’s nothing you can do about it than write it in a way that the compiler won’t think it’s an error. You can’t disable errors because the compiler doesn’t know what to do with the code. It can’t just skip that line from compiling. – Sami Kuhmonen Mar 10 '22 at 12:26
  • 3
    `if constexpr` is your friend. – molbdnilo Mar 10 '22 at 12:29
  • @molbdnilo Thanks! it solved the problem for me :) – Chaitanya Mar 10 '22 at 12:33
  • 1
    The default initialization scares me; maybe you want `*shared == T()`? – Davis Herring Mar 10 '22 at 18:02
  • @DavisHerring `*shared == T()` would be shorter in code but won't it be the same in terms of usage? Are there any shortcomings that I am missing here? – Chaitanya Mar 11 '22 at 15:06
  • 1
    @Chaitanya: It’s value-initialization, which is less likely to produce undefined behavior in the comparison. – Davis Herring Mar 11 '22 at 15:14

1 Answers1

0

Thanks to @molbdnilo for providing the solution. The working function is:

template <typename T>
bool isSharedPtrUninitialized(const std::shared_ptr<T>& shared)
{
    if(shared) {
        if constexpr (has_equate<T>) {
            T tmp;
            if(*shared == tmp)
                return true;
        }
        return false;
    }
    return true;
}

Using if constexpr instead of if solved the problem for me. If curious about the difference between these two then have a look at the post Difference between "if constexpr()" Vs "if()" on SO.

Chaitanya
  • 177
  • 2
  • 9