This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: RFC: basic regex implementation
On 10 June 2010 13:53, Stephen M. Webb wrote:
>
>> A comment on the C++0x regex spec, rather than your implementation:
>> It's my understanding that users are not supposed to instantiate
>> sub_match objects, or at least shouldn't need to, as doing so results
>> in an uninitialised "matched" member. I intend to file an NB comment
>> suggesting a deleted default constructor. ?There could be a private
>> constructor which is used internally by the library. ?If you have any
>> comments on that point I'd be glad to hear them.
>
> The problem with making sub_match constructors private is that the
> implementation of the match engine(s) and token_iterator engine(s) could get
> pretty hairy, or else sub_match would have to have so many friends it should
> have its own page on Facebook. ?A sub_match is effectively a POD, and if a
> user creates a POD without initializing it he or she can keep both halves.
:-)
> I think a safer design might have been to make sub_match.matched a member
> function and provide non-trivial constructors. ?Then again, keeping it
> PODlike simplifies implementing the rest iof the regex library.
It's certainly not a POD, as it has a base class with non-trivial
constructors and the iterator types can be non-POD too. That means
you can't use aggregate initialization, and even value-initialization
(which calls the implicitly-defined default ctor) will not init the
bool member.
Consider:
sub_match sm = sub_match();
if (sm.matched) {
frobnicate(sm.first, sm.second);
}
It's OK for the iterators to be singular, as long as you can check
sm.matched. But a default-constructed sub_match has an uninitialised
'matched' -- I think it should either be safely initialised (via a
non-trivial default constructor) or it should not be possible for
users to default construct a sub_match.
The problem of needing lots of friends can be solved easily in a
couple of ways. With a private helper function:
template<typename BiIter>
constexpr sub_match
__mksm();
template<class BiIter>
class sub_match {
private:
friend constexpr sub_match __mksm<BiIter>();
struct __tag { };
sub_match( __tag );
...
};
template<typename BiIter>
constexpr inline sub_match
__mksm() { return sub_match<BiIter, BiIter>( __tag() ); }
Only that function needs to be a friend of sub_match. The
implementation can use that anywhere it needs to create a sub_match.
Users shouldn't be using anything called __mksm but if they do, they
only have themselves to blame if it goes wrong.
Or just have a public constructor taking a __tag type. Again, users
who use it do so at their own risk, but the documented interface
doesn't allow them to create an object with uninitialised members.
> It would be interesting to hear what the Committee has to say on the matter.
Look out for a ballot comment from the UK on the matter, if I get time
to write it.