Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > legal code?

Reply
Thread Tools

legal code?

 
 
Noah Roberts
Guest
Posts: n/a
 
      12-10-2008
Someone in another list posted this code. It compiles in G++ and
apparently is absorbed by comeau as well. VS vomits.

#include <cstddef>

template < typename T, std :: size_t sz >
struct Block
{
typedef T type[ sz ][ sz ];
};

template < typename T >
void assign( T & assignee, const T & value )
{}

template < typename T, std :: size_t sz >
void assign( T ( & assignee )[ sz ], const T ( & value )[ sz ] )
{}

int main( )
{
Block< int, 16 > :: type a;
const Block< int, 16 > :: type b = { };

assign( a, b );
}


1>e:\dev_workspace\experimental\boost_msg_test\boo st_msg_test\boost_msg_test.cpp(22)
: error C2782: 'void assign(T (&)[sz],const T (&)[sz])' : template
parameter 'T' is ambiguous
1>
e:\dev_workspace\experimental\boost_msg_test\boost _msg_test\boost_msg_test.cpp(14)
: see declaration of 'assign'
1> could be 'const int [16]'
1> or 'int [16]'
1>e:\dev_workspace\experimental\boost_msg_test\boo st_msg_test\boost_msg_test.cpp(22)
: error C2782: 'void assign(T &,const T &)' : template parameter 'T' is
ambiguous
1>
e:\dev_workspace\experimental\boost_msg_test\boost _msg_test\boost_msg_test.cpp(10)
: see declaration of 'assign'
1> could be 'const int [16][16]'
1> or 'int [16][16]'


G++ compiles and calls the T[] version.
 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      12-12-2008
On Dec 10, 7:24 pm, Noah Roberts <(E-Mail Removed)> wrote:
> Someone in another list posted this code. It compiles in G++
> and apparently is absorbed by comeau as well. VS vomits.


> #include <cstddef>


> template < typename T, std :: size_t sz >
> struct Block
> {
> typedef T type[ sz ][ sz ];
> };


> template < typename T >
> void assign( T & assignee, const T & value )
> {}


> template < typename T, std :: size_t sz >
> void assign( T ( & assignee )[ sz ], const T ( & value )[ sz ] )
> {}


> int main( )
> {
> Block< int, 16 > :: type a;
> const Block< int, 16 > :: type b = { };
>
> assign( a, b );
> }


> 1>e:\dev_workspace\experimental\boost_msg_test\boo st_msg_test\boost_msg_test.cpp(22)
> : error C2782: 'void assign(T (&)[sz],const T (&)[sz])' : template
> parameter 'T' is ambiguous
> 1>
> e:\dev_workspace\experimental\boost_msg_test\boost _msg_test\boost_msg_test.cpp(14)
> : see declaration of 'assign'
> 1> could be 'const int [16]'
> 1> or 'int [16]'
> 1>e:\dev_workspace\experimental\boost_msg_test\boo st_msg_test\boost_msg_test.cpp(22)
> : error C2782: 'void assign(T &,const T &)' : template parameter 'T' is
> ambiguous
> 1>
> e:\dev_workspace\experimental\boost_msg_test\boost _msg_test\boost_msg_test.cpp(10)
> : see declaration of 'assign'
> 1> could be 'const int [16][16]'
> 1> or 'int [16][16]'


> G++ compiles and calls the T[] version.


It's a bug in VC++. Both function templates should be
instantiated (and the error message suggests they are) and
participate in overload resolution, but according to §14.5.5.2,
the second is clearly more specialized than the first, and
according to §13.3.3, if all other things are equal (and they
are, or at least they should be), the function instantiated from
the more specialized template is chosen.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
 
Andrey Tarasevich
Guest
Posts: n/a
 
      12-16-2008
Noah Roberts wrote:
> Someone in another list posted this code. It compiles in G++ and
> apparently is absorbed by comeau as well. VS vomits.


A bug in VS prevents it from deducing the template argument properly in
situations when const-array types are involved. The problem can be
easily reproduced with

template <class T> void foo(T& l, const T& r);

int main() {
int l[10];
const int r[10] = {};
foo(l, r);
}

I.e. the original problem with your code has nothing to do with the fact
that 'assign' template is overloaded - it is easily reproducible with
just one template.

You can override the deduction process by specifying the argument
explicitly (e.g. 'foo<int[10]>(l, r)' in my example), but, of course,
this looks pretty ugly as a workaround.

It is worth noting though that if you use that workaround (i.e. call
your 'assign' as 'assign<Block< int, 16 > :: type>( a, b )' VS does
correctly select the more specialized second version of 'assign'.

--
Best regards,
Andrey Tarasevich
 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      12-16-2008
Andrey Tarasevich wrote:
> Noah Roberts wrote:
>> Someone in another list posted this code. It compiles in G++ and
>> apparently is absorbed by comeau as well. VS vomits.

>
> A bug in VS prevents it from deducing the template argument properly in
> situations when const-array types are involved. The problem can be
> easily reproduced with
>
> template <class T> void foo(T& l, const T& r);
>
> int main() {
> int l[10];
> const int r[10] = {};
> foo(l, r);
> }
>
> I.e. the original problem with your code has nothing to do with the fact
> that 'assign' template is overloaded - it is easily reproducible with
> just one template.
>
> You can override the deduction process by specifying the argument
> explicitly (e.g. 'foo<int[10]>(l, r)' in my example), but, of course,
> this looks pretty ugly as a workaround.
>
> It is worth noting though that if you use that workaround (i.e. call
> your 'assign' as 'assign<Block< int, 16 > :: type>( a, b )' VS does
> correctly select the more specialized second version of 'assign'.
>


Thanks. I actually helped the guy figure this out a while back. I
think that MSVC is deducing "T" as "int[]" and then calling THAT
const...and not doing so correctly (in that it would cascade down to int
instead of int[]). My reply to them explaining this:

Noah Roberts wrote:



> In int const x[5][5], the int contained within the dual array is the

constant. In the case of T const& value[] though it is T that is const,
which is an array. This is nonsense I believe (arrays are always
r-values). VS seems to have no way to handle it while the others do.

I think this is a bug in VS.

At first I thought that what I was doing and what you are doing where
different because you had a typedef int[size][size] that you later
declare a const object of. I thought maybe this actually made the
*array* const but I was mistaken. The standard quite clearly states,
with example, that even when you are doing that to a typedef of array
type...the const applies to the elements, not to the array. The
provided example from 8.3.4/1:

typedef int A[5], AA[2][3];
typedef const A CA; // type is "array of 5 const int"
typedef const AA CAA; // type is "array of 2 array of 3 const int"

It doesn't get less ambiguous than that.

That means, to me, that even when T is an array type, expecting a const
reference of that type should resolve in the same manner and your
template should resolve. As someone mentioned in comp.lang.c++ your
second version (the one expecting an array) is a closer match and should
be the one used.

I think there's a bug in msvc in template typing. I'd bet that it's
considering const T (&ref)[size] to be an /array of const array of int/
when passed an /array of array of const int/, which is nonsense in C++
and would never resolve to anything.

My answer to their immediate problem:

Don't recall if it was said already but you can also explicitly say
which type you're using:

int main( )
{
Block< int, 16 > :: type a;
const Block< int, 16 > :: type b = { };

assign<int[16]>( a, b );
}

Then you'll need to establish template metaprograms to remove one array
level from a type and get the type beneath in order to write your
recursive template call so that it can cast the next level:

template < typename T >
struct next_level
{
typedef T type;
};

template < typename T, size_t sz >
struct next_level<T[sz]>
{
typedef T type;
};

template < typename T >
void assign( T & assignee, const T & value )
{
assignee = value;
}
template < typename T, std :: size_t sz >
void assign( T ( & assignee )[ sz ], const T ( & value )[ sz ] )
{
for (size_t i = 0; i < sz; ++i)
assign<typename next_level<T>::type>(assignee[i], value[i]);
}


Tested and works in msvc:


int main( )
{
typedef Block<int,3>::type type_t;
type_t a;
type_t const b = { { 1,2,3}, {4,5,6}, {7,8,9} };

assign<int[3]>( a, b );

for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
std::cout << a[i][j] << " ";
std::cout << std::endl;
}

std::cin.get();
}
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is it legal to write an logical equation for a FPGA LUT in claims of a patent? Weng Tianxiang VHDL 12 12-10-2005 03:49 PM
Research: File-sharers big legal download spenders. Silverstrand Front Page News 0 07-27-2005 03:00 PM
State machine transition on internal signals - is it legal? Divyang M VHDL 9 05-18-2005 03:58 PM
State machine transition on internal signals -- is it legal? Divyang M VHDL 1 05-15-2005 09:36 AM
Is this legal? Valentin Tihomirov VHDL 20 10-29-2003 10:31 AM



Advertisments