Mostly you have to assume that users of your code are competent.
But this is a political world. So maybe sometimes you may have to do a probabilistic best effort to prevent mishaps. E.g.,
#include <assert.h>
#include <string>
class StdString: public std::string
{
private:
using std::string::c_str;
using std::string::data;
public:
StdString( char const* const s ): std::string( s ) { assert( s != nullptr ); }
};
StdString foo() { return "Bah!"; }
int main()
{
std::string const a = foo();
char const* const b = foo().c_str(); //! Nyet.
}
Maybe throw in a move constructor there for good measure, but generally perfect efficiency is in conflict with perfect safety and perfect clarity, e.g. can has 2 but not 3.