Usage of __for_bool_ value in __nat {} classes

I was looking through clang’s c++ standard library, and found this class in the shared_ptr class.

class shared_ptr
...
private:
        struct __nat {int __for_bool_;};
...
};

and I understand that this class is used to detect whether type conversion is possible at compile time, but its member _for_bool is never used anywhere in the class or the weak_ptr counterpart. So my question is, what is the point of _for_bool, why not simply use an empty class for the same purpose?

I’m sure the standard library authors definitely knows better than me. Please help.

Thanks,
Zeyang

I’m not sure what the purpose is. I agree it doesn’t seem to have any effect, and the git blame comes back to the initial commit for libc++.
Changing the layout of __nat now would be an ABI break; so that’s out of the question. But I have some upcoming patches that are going
to remove most usages of it.

@Howard, do you recall what the purpose of this was? Something to do with initializing empty structs maybe?

/Eric

Looks like the initial purpose was to implement a poor man’s explicit operator bool that returned a pointer to member, but it was removed in r151088.

@Erik, Thanks for digging through the history!

I still look forward to removing it after moving the SFINAE into the template parameter list.

/Eric

That sounds right to me.

Howard

@Eric,

Could you elaborate a bit what it means to move the SFINAE into the template parameter list? Does it mean the enable_if conversion check could be moved to the template parameter list and remove the default __nat parameter? Does that have any performance implication?

I’m really interested to know as I’m writing my own version of shared_ptr without atomics.
Thanks!

Zeyang

@Eric,

Could you elaborate a bit what it means to move the SFINAE into the
template parameter list? Does it mean the enable_if conversion check could
be moved to the template parameter list and remove the default __nat
parameter?

Yep, you got it. That's what it entails.

Does that have any performance implication?

You'll be passing one less parameter, so yes, there will be less codegen.
Though I'm not necessarily doing it for that reason.

I personally find using default function arguments for SFINAE to be a worse
solution than default template parameters. Users are able
to accidentally pass "{}" to the function parameter, which should really be
ill-formed. I also find the default template parameter
SFINAE easier to read.