Log On
Embarcadero Home
Watch, Follow, &
Connect with Us
Share This
QualityCentral
Communities
Articles
Blogs
Resources
Downloads
Help
QualityCentral
Delphi-BCB
RTL
C++
Delphi
Arithmetic
ConvUtils
Date - Time
DateUtils
File Management
Format + Float
Input/Output
Math Unit
Memory, Pointer, Address
Null-terminated strings
Other Classes
Other RTL
Pascal Strings
Regular Expressions
RTL Exceptions
Text Files
Thread support
Typed/Untyped Files
WinAPI
You are not logged in.
Help
Print
Public Report
Report From:
Delphi-BCB/RTL/Delphi
[ Add a report in this area ]
Report #:
106246
Status:
Open
array of string fails to be recognised
Project:
Delphi
Build #:
any
Version:
16.4
Submitted By:
Dmitry Burov
Report Type:
Suggestion / Enhancement Request
Date Reported:
6/7/2012 7:13:08 AM
Severity:
Extreme corner case
Last Updated:
8/6/2012 1:00:20 PM
Platform:
All platforms
Internal Tracking #:
Resolution:
None
(Resolution Comments)
Resolved in Build:
:
None
Duplicate of:
None
Voting and Rating
Overall Rating:
No Ratings Yet
0.00 out of 5
Total Votes:
10
Description
This is a issue of RTL design.
'System.TArray<System.string>' and 'TStringDynArray' is not compatible.
For example,
uses Classes, IOUtils;
This works:
TStringList.Create.AddStrings(
TArray<string>(
TDirectory.GetFiles('c:\', '*.dll') ) );
This gives an error
[DCC Error] Unit1.pas(37): E2250 There is no overloaded version of 'AddStrings' that can be called with these arguments
TStringList.Create.AddStrings(
TDirectory.GetFiles('c:\', '*.dll') ) ;
GetFiles return type is
System.Types.TStringDynArray = array of string;
AddStrings expected param type is const Strings: TArray<string> and that is System.TArray<T> = array of T;
So both types ARE array of string.
None of them is alienated with typecast forbidding construction "type x = TYPE y;"
They ARE the same,
Yet compiler cannot find a proper function...
Either compiler is very wrong here, or RTL is very inconsistent and should be brought to common types set.
Steps to Reproduce:
This is a issue of RTL design.
'System.TArray<System.string>' and 'TStringDynArray' is not compatible.
For example,
Add this unit to any project and try to compile.
---------------------------
unit dummy.
interface
implementation
uses Classes, IOUtils;
procedure CompileMe;
begin
TStringList.Create.AddStrings(
TDirectory.GetFiles('c:\', '*.dll') ) ;
(* yes, memory leak. Don't bother, the question here is
ability to compile it without explicit typecasting
to yet another alias of the same array-of-string type
nor additional temporary var created to pollute namespace *)
end;
end.
---------------------------
This gives an error
[DCC Error] Unit1.pas(37): E2250 There is no overloaded version of 'AddStrings' that can be called with these arguments
[System.IOUtils.pas]
---------------------------
TDirectory = record
....
class function GetFiles(const Path: string): TStringDynArray;
overload; inline; static;
....
---------------------------
[System.Classes.pas]
---------------------------
....
TStrings = class(TPersistent)
....
public
....
procedure AddStrings(Strings: TStrings); overload; virtual;
procedure AddStrings(const Strings: TArray<string>); overload;
procedure AddStrings(const Strings: TArray<string>; const Objects: TArray<TObject>); overload;
....
---------------------------
Workarounds
None
Attachment
None
Comments
Tomohiro Takahashi at 6/7/2012 6:30:11 PM
-
Could you please attach sample project to reproduce/verify your issue?
Dmitry Burov at 6/7/2012 10:52:14 PM
-
steps to reproduction is all u need.
It just would not compile.
okay, let's add some boilerplate, if u insist.
===
unit dummy.
interface
implementation
uses Classes, IOUtils;
procedure CompileMe;
begin
TStringList.Create.AddStrings(
TDirectory.GetFiles('c:\', '*.dll') ) ;
(* yes, memory leak. Don't bother, the question here is
ability to compile it without explicit typecasting
to yet another alias of the same array-of-string type
nor additional temporary var created to pollute namespace *)
end;
====
Add this unit to any project and try to compile.
Tomohiro Takahashi at 6/8/2012 8:56:27 PM
-
How about using class helper as below?
------------------------------------
type
TStringListHelper = class helper for TStringList
procedure AddStrings(const Strings: TStringDynArray);
end;
{ TStringListHelper }
procedure TStringListHelper.AddStrings(const Strings: TStringDynArray);
var
I: Integer;
begin
BeginUpdate;
try
for I := Low(Strings) to High(Strings) do
Add(Strings[I]);
finally
EndUpdate;
end;
end;
procedure CompileMe;
begin
TStringList.Create.AddStrings(TDirectory.GetFiles('c:\', '*.dll'));
end;
------------------------------------
Dmitry Burov at 6/10/2012 5:44:18 AM
-
BTW, that is not elegant helper.
Elegant would enforce that type is the same no matter if used name aliases are different
{ TStringListHelper }
procedure TStringListHelper.AddStrings(const Strings: TStringDynArray);
begin
AddStrings( TArrray<string>( Strings ) );
end;
procedure CompileMe;
begin
TStringList.Create.AddStrings(TDirectory.GetFiles('c:\', '*.dll'));
end;
----
which again prooves that those are different names to the same type, and the compiler DOESKNOW it, but just fails to use it somehow, until hinted by programmer
Dmitry Burov at 6/10/2012 5:37:34 AM
-
yeah, that might do.
But why should it be required at all ?
The question is not hwow to work around this, but why it happens in the first place
Tomohiro Takahashi at 6/8/2012 8:39:05 PM
-
Thanks.
I updated [Steps] field.
> Either compiler is very wrong here, or RTL is very inconsistent ...
This is a issue of RTL design.
Dmitry Burov at 6/10/2012 5:41:14 AM
-
why so?
why shouldn't those types be compatible ?
No, wrong queston.
Why those aliases to the same type are not recognised as the same type they are ?
again, they are not "type x = type y" that would break the equivalence.
They are "type x = y" which means "that very type by new name"
To me making such commmon type as dynamic array incompatible with TArray<X> not only having no sence, but frankly making TArray<x> practically useless.
If compiler cannot be fixed, i believe implicit typecasts should be made part of TArray<x> definition if possible.
Dmitry Burov at 6/15/2012 1:40:03 AM
-
I ask the compiler architects to rethink this.
It is done with lines of Pascal Report of 1949.
But back then you even can not have non-named arrays as procedure parameters, only typedef'ed ones!
After Turbo Pascal introduced "Open Arrays" and Delphi introduced "Dynamic Arrays" - there is no reason to keep this limitation.
Look,
tpy T1 = set of byte; T2 = set of byte;
Those types are different too "to the book". But they can be assigned/passed/all that. Becausekeeping them incompatible as Wirth did is impractical outside school labs.
Open documentation about types, and you will read "types that and that are different. But that is so impractical, that we made name them 'different yet compatible' and effectively remove that isolation barrier'
If some political question insists calling all array types 'different' - be it. But call them compatible, like u did with open arrays and dynamic arrays - which "by the letter" should not work in Pascal for the same very reasons my code does not compile.
Cause today, not back in 1949, it is so out of all trends!
* Against the trend of all programming languages.
* Against the trend of TurboPascal/Delphi evolution.
* Against the composability pinciples lying behind all RADs and all generics.
The very fact that RTL architects made this mistake shows how ultimately ignorant and reasonlessly restrictive that incompatibility it. Most experienced and bright programmers of yours just could no think that arrays does not allow that every other type easily and naturally uses.
http://stackoverflow.com/questions/11029353
This restriction just dows not have any practical sense half-decade after 1949.
It has a number of bad consequences and no single good effect today.
Time to lift it.
And it would not be even breaking Pascal codebook, for it only describes fixed arrays.
Open arrays and dynamic arrays are not pascal types, just like generics.
Open arrays and dynamic arrays have no reason to be limited by 1949 restrictions, just like generics array is free of them!
Dmitry Burov at 9/25/2012 11:20:08 PM
-
One more reason why they SHOULD BE compatible. From StackOverflow 12578185
---
procedure Some(Buf :TByteDynArray); overload;
begin
Writeln('Byte dynamic array');
end;
procedure Some(Buf :TArray<Byte>); overload;
begin
Writeln('TBytes AKA byte generic array');
end;
---
This happily compiled but can leads to ambiguos error when calling Some(nil);
In other words, compiler really treats them the same type and cannot distinguish which to call. Because they ARE the same.
View Your Reports
Search
Server Response from: ETNACODE01
Developer Tools
Blackfish SQL
C++Builder
Delphi
FireMonkey
Prism
InterBase
JBuilder
J Optimizer
HTML5 Builder
3rdRail & TurboRuby
Database Tools
Change Manager
DBArtisan
DB Optimizer
ER/Studio
Performance Center
Rapid SQL
Technical Articles
Tutorials
White Papers
Press Releases
Newsletters
Add Content (GetPublished)
Audio
Audio & Video
Video
Bugs & Suggestions (QualityCentral)
Discussion Forums
Examples (CodeCentral)
Tags
Technology Partners
Downloads
Free Trials
Registered User Downloads
Beta Programs
Add Content (GetPublished)
Articles
Blogs
Bugs & Suggestions (QualityCentral)
Discussion Forums
Examples (CodeCentral)
Member Services
About
Connect with Us