www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - main.d(61): Error: temp_[i_] isn't mutable

reply Ben Hanson <Ben.Hanson tfbplc.co.uk> writes:
Hi there,

I'm converting the following C++ function to D:

    void negate ()
    {
        const std::size_t max_chars_ = sizeof (CharT) == 1 ?
            num_chars : num_wchar_ts;
        CharT curr_char_ = sizeof (CharT) == 1 ? -128 : 0;
        string temp_;
        const CharT *curr_ = _charset.c_str ();
        const CharT *chars_end_ = curr_ + _charset.size ();

        _negated = !_negated;
        temp_.resize (max_chars_ - _charset.size ());

        CharT *ptr_ = const_cast<CharT *> (temp_.c_str ());
        std::size_t i_ = 0;

        while (curr_ < chars_end_)
        {
            while (*curr_ > curr_char_)
            {
                *ptr_ = curr_char_;
                ++ptr_;
                ++curr_char_;
                ++i_;
            }

            ++curr_char_;
            ++curr_;
            ++i_;
        }

        for (; i_ < max_chars_; ++i_)
        {
            *ptr_ = curr_char_;
            ++ptr_;
            ++curr_char_;
        }

        _charset = temp_;
    }

Here's the complete source:

module main;

import std.algorithm;
import std.string;

template regex(StringT)
{
struct basic_string_token
{
    bool _negated = false;
	StringT _charset;
	typedef typeof(StringT.init[0]) CharT;
	enum size_t MAX_CHARS = CharT.max + 1;

	this(const bool negated_, ref StringT charset_)
	{
		_negated = negated_;
		_charset = charset_;
	}

	void remove_duplicates()
	{
		_charset.sort;
		_charset = squeeze(_charset);
	}

	void normalise()
	{
		if (_charset.length == MAX_CHARS)
		{
            _negated = !_negated;
			_charset.clear();
		}
		else if (_charset.length > MAX_CHARS / 2)
		{
			negate();
		}
	}

	void negate()
	{
		CharT curr_char_ = MAX_CHARS == 256 ? 0x80 : 0;
		StringT temp_;
		size_t curr_ = 0;
		size_t end_ = _charset.length;
		size_t i_ = 0;

        _negated = !_negated;
		temp_.length = MAX_CHARS - end_;

		while (curr_ < end_)
		{
			while (_charset[curr_] > curr_char_)
			{
				temp_[i_] = curr_char_;
				++curr_char_;
				++i_;
			}

            ++curr_char_;
            ++curr_;
            ++i_;
		}

        for (; i_ < MAX_CHARS; ++i_)
        {
            temp_ ~= curr_char_;
            ++curr_char_;
        }

		_charset = temp_;
	}
};
}

int main(char[][]argv)
{
	regex!(string).basic_string_token token_;

	token_._charset = "cccbba";
	token_.remove_duplicates();
	token_.negate();
	return 0;
}

Can anyone explain the error 'main.d(61): Error: temp_[i_] isn't
mutable'? Can I use pointers instead like the C++ code? What's the
best approach for maximum efficiency in D (pointers would make the
conversion easier to, I guess).

Thanks,

Ben
Jun 19 2010
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 06/19/2010 12:30 PM, Ben Hanson wrote:
 Hi there,

 I'm converting the following C++ function to D:

      void negate ()
      {
          const std::size_t max_chars_ = sizeof (CharT) == 1 ?
              num_chars : num_wchar_ts;
          CharT curr_char_ = sizeof (CharT) == 1 ? -128 : 0;
          string temp_;
          const CharT *curr_ = _charset.c_str ();
          const CharT *chars_end_ = curr_ + _charset.size ();

          _negated = !_negated;
          temp_.resize (max_chars_ - _charset.size ());

          CharT *ptr_ = const_cast<CharT *>  (temp_.c_str ());
          std::size_t i_ = 0;

          while (curr_<  chars_end_)
          {
              while (*curr_>  curr_char_)
              {
                  *ptr_ = curr_char_;
                  ++ptr_;
                  ++curr_char_;
                  ++i_;
              }

              ++curr_char_;
              ++curr_;
              ++i_;
          }

          for (; i_<  max_chars_; ++i_)
          {
              *ptr_ = curr_char_;
              ++ptr_;
              ++curr_char_;
          }

          _charset = temp_;
      }

 Here's the complete source:

 module main;

 import std.algorithm;
 import std.string;

 template regex(StringT)
 {
 struct basic_string_token
 {
      bool _negated = false;
 	StringT _charset;
 	typedef typeof(StringT.init[0]) CharT;
 	enum size_t MAX_CHARS = CharT.max + 1;

 	this(const bool negated_, ref StringT charset_)
 	{
 		_negated = negated_;
 		_charset = charset_;
 	}

 	void remove_duplicates()
 	{
 		_charset.sort;
 		_charset = squeeze(_charset);
 	}

 	void normalise()
 	{
 		if (_charset.length == MAX_CHARS)
 		{
              _negated = !_negated;
 			_charset.clear();
 		}
 		else if (_charset.length>  MAX_CHARS / 2)
 		{
 			negate();
 		}
 	}

 	void negate()
 	{
 		CharT curr_char_ = MAX_CHARS == 256 ? 0x80 : 0;
 		StringT temp_;
 		size_t curr_ = 0;
 		size_t end_ = _charset.length;
 		size_t i_ = 0;

          _negated = !_negated;
 		temp_.length = MAX_CHARS - end_;

 		while (curr_<  end_)
 		{
 			while (_charset[curr_]>  curr_char_)
 			{
 				temp_[i_] = curr_char_;
 				++curr_char_;
 				++i_;
 			}

              ++curr_char_;
              ++curr_;
              ++i_;
 		}

          for (; i_<  MAX_CHARS; ++i_)
          {
              temp_ ~= curr_char_;
              ++curr_char_;
          }

 		_charset = temp_;
 	}
 };
 }

 int main(char[][]argv)
 {
 	regex!(string).basic_string_token token_;

 	token_._charset = "cccbba";
 	token_.remove_duplicates();
 	token_.negate();
 	return 0;
 }

 Can anyone explain the error 'main.d(61): Error: temp_[i_] isn't
 mutable'? Can I use pointers instead like the C++ code? What's the
 best approach for maximum efficiency in D (pointers would make the
 conversion easier to, I guess).

 Thanks,

 Ben
because strings aren't mutable. char[]'s on the other hand are, so you could just change temp_'s type to import std.traits; Unqual!(typeof(StringT.init[0]))[] temp_; or something like that.
Jun 19 2010
parent Ben Hanson <Ben.Hanson tfbplc.co.uk> writes:
 because strings aren't mutable. char[]'s on the other hand are, so you
 could just change temp_'s type to
 import std.traits;
 Unqual!(typeof(StringT.init[0]))[] temp_;
 or something like that.
Thanks Ellery.
Jun 19 2010
prev sibling parent reply Justin Spahr-Summers <Justin.SpahrSummers gmail.com> writes:
On Sat, 19 Jun 2010 17:30:26 +0000 (UTC), Ben Hanson 
<Ben.Hanson tfbplc.co.uk> wrote:
 Here's the complete source:
 
 module main;
 
 import std.algorithm;
 import std.string;
 
 template regex(StringT)
 {
 struct basic_string_token
 {
     bool _negated = false;
 	StringT _charset;
 	typedef typeof(StringT.init[0]) CharT;
 	enum size_t MAX_CHARS = CharT.max + 1;
 
 	this(const bool negated_, ref StringT charset_)
 	{
 		_negated = negated_;
 		_charset = charset_;
 	}
 
 	void remove_duplicates()
 	{
 		_charset.sort;
 		_charset = squeeze(_charset);
 	}
 
 	void normalise()
 	{
 		if (_charset.length == MAX_CHARS)
 		{
             _negated = !_negated;
 			_charset.clear();
 		}
 		else if (_charset.length > MAX_CHARS / 2)
 		{
 			negate();
 		}
 	}
 
 	void negate()
 	{
 		CharT curr_char_ = MAX_CHARS == 256 ? 0x80 : 0;
 		StringT temp_;
 		size_t curr_ = 0;
 		size_t end_ = _charset.length;
 		size_t i_ = 0;
 
         _negated = !_negated;
 		temp_.length = MAX_CHARS - end_;
 
 		while (curr_ < end_)
 		{
 			while (_charset[curr_] > curr_char_)
 			{
 				temp_[i_] = curr_char_;
 				++curr_char_;
 				++i_;
 			}
 
             ++curr_char_;
             ++curr_;
             ++i_;
 		}
 
         for (; i_ < MAX_CHARS; ++i_)
         {
             temp_ ~= curr_char_;
             ++curr_char_;
         }
 
 		_charset = temp_;
 	}
 };
 }
 
 int main(char[][]argv)
 {
 	regex!(string).basic_string_token token_;
 
 	token_._charset = "cccbba";
 	token_.remove_duplicates();
 	token_.negate();
 	return 0;
 }
 
 Can anyone explain the error 'main.d(61): Error: temp_[i_] isn't
 mutable'? Can I use pointers instead like the C++ code? What's the
 best approach for maximum efficiency in D (pointers would make the
 conversion easier to, I guess).
 
 Thanks,
 
 Ben
"string" is actually an alias for "immutable(char)[]" (and similarly for the other string types), so its contents are not modifiable, though its length can be adjusted and contents appended. If you need to be able to modify the characters, just use char[] instead. You can then use the .idup property to get a string afterward.
Jun 19 2010
next sibling parent Ben Hanson <Ben.Hanson tfbplc.co.uk> writes:
Hi Justin,

== Quote from Justin Spahr-Summers (Justin.SpahrSummers gmail.com)'s article
 "string" is actually an alias for "immutable(char)[]" (and similarly for
 the other string types), so its contents are not modifiable, though its
 length can be adjusted and contents appended. If you need to be able to
 modify the characters, just use char[] instead. You can then use the
 .idup property to get a string afterward.
Thanks for the clarification! Regards, Ben
Jun 19 2010
prev sibling parent reply Ben Hanson <Ben.Hanson tfbplc.co.uk> writes:
== Quote from Justin Spahr-Summers (Justin.SpahrSummers gmail.com)'s
 "string" is actually an alias for "immutable(char)[]" (and
similarly for
 the other string types), so its contents are not modifiable, though
its
 length can be adjusted and contents appended. If you need to be
able to
 modify the characters, just use char[] instead. You can then use the
 .idup property to get a string afterward.
I'm converted temp_ to CharT[] as suggested, but the conversion back to a string is failing: _charset = temp_.idup; main.d(76): Error: cannot implicitly convert expression (_adDupT((& D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast (string)temp_)) of type immutable(CharT)[] to string
Jun 20 2010
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Ben Hanson wrote:
 == Quote from Justin Spahr-Summers (Justin.SpahrSummers gmail.com)'s
 "string" is actually an alias for "immutable(char)[]" (and
similarly for
 the other string types), so its contents are not modifiable, though
its
 length can be adjusted and contents appended. If you need to be
able to
 modify the characters, just use char[] instead. You can then use the
 .idup property to get a string afterward.
I'm converted temp_ to CharT[] as suggested, but the conversion back to a string is failing: _charset = temp_.idup; main.d(76): Error: cannot implicitly convert expression (_adDupT((& D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast (string)temp_)) of type immutable(CharT)[] to string
Would it work for you if the regex template took the character type instead of the string type? The relevant lines: template regex(CharT) { // ... alias CharT[] StringT; StringT _charset; enum size_t MAX_CHARS = CharT.max + 1; // ... _charset = squeeze(_charset.idup).dup; And then, in main: regex!(char).basic_string_token token_; Ali
Jun 20 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/20/2010 12:56 PM, Ali Çehreli wrote:
 Ben Hanson wrote:
 == Quote from Justin Spahr-Summers (Justin.SpahrSummers gmail.com)'s
 "string" is actually an alias for "immutable(char)[]" (and
similarly for
 the other string types), so its contents are not modifiable, though
its
 length can be adjusted and contents appended. If you need to be
able to
 modify the characters, just use char[] instead. You can then use the
 .idup property to get a string afterward.
I'm converted temp_ to CharT[] as suggested, but the conversion back to a string is failing: _charset = temp_.idup; main.d(76): Error: cannot implicitly convert expression (_adDupT((& D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast (string)temp_)) of type immutable(CharT)[] to string
Would it work for you if the regex template took the character type instead of the string type? The relevant lines: template regex(CharT) { // ... alias CharT[] StringT; StringT _charset; enum size_t MAX_CHARS = CharT.max + 1; // ... _charset = squeeze(_charset.idup).dup; And then, in main: regex!(char).basic_string_token token_; Ali
IMHO it's more general if the regexp took the string type as a parameter. This is because later that is easier generalizable to accepting a range that's different from an array. My dream: to have a compile-time-generated regex engine that can operate on any input stream. Andrei
Jun 20 2010
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Andrei Alexandrescu wrote:

 IMHO it's more general if the regexp took the string type as a
 parameter. This is because later that is easier generalizable to
 accepting a range that's different from an array.
Agreed. Given T which may be an immutable type, what is the cleanest way of creating a mutable copy of that type? typeof(array.dup) works on arrays but what if T is a value type or any type where .dup doesn't exist? Ali
Jun 20 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/20/2010 02:29 PM, Ali Çehreli wrote:
 Andrei Alexandrescu wrote:

  > IMHO it's more general if the regexp took the string type as a
  > parameter. This is because later that is easier generalizable to
  > accepting a range that's different from an array.

 Agreed.

 Given T which may be an immutable type, what is the cleanest way of
 creating a mutable copy of that type? typeof(array.dup) works on arrays
 but what if T is a value type or any type where .dup doesn't exist?

 Ali
std.conv.to should work with most sensible combinations. Andrei
Jun 20 2010
prev sibling parent reply Ben Hanson <Ben.Hanson tfbplc.co.uk> writes:
Hi Andrei,

== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 On 06/20/2010 12:56 PM, Ali Çehreli wrote:
 Ben Hanson wrote:
 == Quote from Justin Spahr-Summers (Justin.SpahrSummers gmail.com)'s
 "string" is actually an alias for "immutable(char)[]" (and
similarly for
 the other string types), so its contents are not modifiable, though
its
 length can be adjusted and contents appended. If you need to be
able to
 modify the characters, just use char[] instead. You can then use the
 .idup property to get a string afterward.
I'm converted temp_ to CharT[] as suggested, but the conversion back to a string is failing: _charset = temp_.idup; main.d(76): Error: cannot implicitly convert expression (_adDupT((& D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast (string)temp_)) of type immutable(CharT)[] to string
Would it work for you if the regex template took the character type instead of the string type? The relevant lines: template regex(CharT) { // ... alias CharT[] StringT; StringT _charset; enum size_t MAX_CHARS = CharT.max + 1; // ... _charset = squeeze(_charset.idup).dup; And then, in main: regex!(char).basic_string_token token_; Ali
IMHO it's more general if the regexp took the string type as a parameter. This is because later that is easier generalizable to accepting a range that's different from an array. My dream: to have a compile-time-generated regex engine that can operate on any input stream. Andrei
I'm currently using strings for the regex strings themselves. In lexertl, I use templated free functions what work with iterators, which means input can come from different sources. This sounds like the kind of thing you are talking about? Regards, Ben
Jun 21 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/21/2010 03:37 AM, Ben Hanson wrote:
 I'm currently using strings for the regex strings themselves. In lexertl, I use
 templated free functions what work with iterators, which means input can come
 from different sources. This sounds like the kind of thing you are talking
 about?

 Regards,

 Ben
Sounds about right! Andrei
Jun 21 2010
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/20/2010 07:01 AM, Ben Hanson wrote:
 == Quote from Justin Spahr-Summers (Justin.SpahrSummers gmail.com)'s
 "string" is actually an alias for "immutable(char)[]" (and
similarly for
 the other string types), so its contents are not modifiable, though
its
 length can be adjusted and contents appended. If you need to be
able to
 modify the characters, just use char[] instead. You can then use the
 .idup property to get a string afterward.
I'm converted temp_ to CharT[] as suggested, but the conversion back to a string is failing: _charset = temp_.idup; main.d(76): Error: cannot implicitly convert expression (_adDupT((& D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast (string)temp_)) of type immutable(CharT)[] to string
import std.conv; ... _charset = to!(typeof(_charset))(temp_); "to" converts strings of any width and mutability to strings of any width and mutability. Andrei
Jun 20 2010
prev sibling parent Justin Spahr-Summers <Justin.SpahrSummers gmail.com> writes:
On Sun, 20 Jun 2010 12:01:31 +0000 (UTC), Ben Hanson 
<Ben.Hanson tfbplc.co.uk> wrote:
 
 == Quote from Justin Spahr-Summers (Justin.SpahrSummers gmail.com)'s
 "string" is actually an alias for "immutable(char)[]" (and
similarly for
 the other string types), so its contents are not modifiable, though
its
 length can be adjusted and contents appended. If you need to be
able to
 modify the characters, just use char[] instead. You can then use the
 .idup property to get a string afterward.
I'm converted temp_ to CharT[] as suggested, but the conversion back to a string is failing: _charset = temp_.idup; main.d(76): Error: cannot implicitly convert expression (_adDupT((& D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast (string)temp_)) of type immutable(CharT)[] to string
Sorry I missed this on the first run through. Since you're using typedef to create your CharT type, it will create a type independent from all the others, meaning no implicit casts to or from it. "alias" is the equivalent to a C/C++ "typedef", and that should fix the compilation error.
Jun 20 2010