Template code compilation issue

Template code compilation issue

hi all
here is a code which does not compile with icc11
i think there is a bug in the compiler

#include
using std::cout;
using std::endl;

namespace tag {
struct storage {};
template struct expression {};
}//namespace tag

template
struct tag_complexity { enum { value = 0 }; };
template
struct tag_complexity > { enum { value = c }; };

struct general {};
struct shapeX {};

template
struct expression : public expression::value>, general>
{};
template
struct expression
{};

struct too : public expression
{};

struct gives : public expression
{};

template
void foo(const expression &a)
{ cout << "foo reports\n " << typeid(a).name() << "\n\n"; return; }

template struct subexpression;
template
struct subexpression > :
public expression >,
tag::expression::value>,
shape
>
{
subexpression(const expr_t&) {}
};

template inline
subexpression >
bar(const expression &a)
{
cout << "bar reports\n " << typeid(a).name() << "\n\n";
return static_cast(a);
}

int main()
{
{
too trivial;
foo(trivial);
foo(bar(trivial));
}
{
gives error;

foo(error);
foo >(error);

foo(bar(error)); //comment this line in order to compile
foo(
/*icc 11.0.066 can not match an instance of bar() with 'error'
given hierarchy for 'gives' class
expression, general>
^
expression
^
gives
template arguments for bar() should be deduced at least as*/
bar(error)
);//foo(
}
return 0;
}

16 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Quoting - de666
hi all
here is a code which does not compile with icc11
i think there is a bug in the compiler

Is it on Linux? IA32 or Intel 64 etc.

please post the full compiler version and the compile options.

Thanks,
Jennifer

intel c++ compiler for windows* ia32 v.11.0.066
compiler options are that msvs2005 offers after project conversion (from msvc to intel project) in other words they are pretty much standard
if you need more information i try to collect and post it tomorrow

Quoting - de666

intel c++ compiler for windows* ia32 v.11.0.066
compiler options are that msvs2005 offers after project conversion (from msvc to intel project) in other words they are pretty much standard
if you need more information i try to collect and post it tomorrow

I copy/pasted the code to tp.cpp and VC2005 can not compile as well. Attached the tp.cpp. could you fix it?

>>cl /Od /EHsc tp.cpp
Microsoft 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

tp.cpp
tp.cpp(64) : error C2784: 'void foo(const expression &)' : could not deduce template argument for
'const expression &' from 'gives'
tp.cpp(32) : see declaration of 'foo'
tp.cpp(64) : error C2784: 'void foo(const expression &)' : could not deduce template argument for
'const expression &' from 'gives'
tp.cpp(32) : see declaration of 'foo'
tp.cpp(64) : error C2782: 'void foo(const expression &)' : template parameter 'tag' is ambiguous
tp.cpp(32) : see declaration of 'foo'
could be 'tag::expression'
with
[
c=0
]
or 'tag::storage'

C:temp

Attachments: 

AttachmentSize
Downloadtext/x-c++src tp.cpp2.29 KB

a funny thing about this piece is that it does not compile with msvc80 either...
if you comment the line "foo(error);" wich contains the error (in msvc view) it should compile

ps
i posted the same code to ms technet pointingto that very issue

Quoting - de666

a funny thing about this piece is that it does not compile with msvc80 either...
if you comment the line "foo(error);" wich contains the error (in msvc view) it should compile

ps
i posted the same code to ms technet pointingto that very issue

Ok. I can see the error now.

I'll file a bug report for it. Thanks for getting a small testcase!

Jennifer

>>icl /c /EHsc /Od tp.cpp
Intel C++ Compiler Professional for applications running on IA-32, Version 11.1 Build 20091012 Package ID: w_cproc
_p_11.1.051
Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

tp.cpp
tp.cpp(66): error: no instance of function template "bar" matches the argument list
argument types are: (gives)
foo(bar(error)); //comment this line in order to compile
^

tp.cpp(66): error: no instance of function template "foo" matches the argument list
argument types are: ()
foo(bar(error)); //comment this line in order to compile
^

compilation aborted for tp.cpp (code 2)

thanks for your response
i would like to know if this "little" testcase really is legal since it would be a VERY convenient feature (at least for me)

ps
i attached the msvc/icc project just in case

Attachments: 

AttachmentSize
Downloadapplication/rar cpp_project.rar3.47 KB

I got our engineer's response. Your code is ilegal. It's strange that VC compiles.

You should change the following code:
foo(bar(error)); //comment this line in order to compile

to:

foo(bar((expression) error)); //comment this line in order to compile

Thanks,
Jennifer

hi there
distressingly this really is an illegal code because primary template inherits a specialization wich is incompleteat the point and unfortunately there is no way to define a specialization before the primary template
sad
however icc11 compiles that part, that is you can create an object of type derived from an incomplete typeat the point of declaration (don't bother understanding this paragraph)
the happiness was so close...

Here is a simpler example which compiles with cl but not icl.

template
struct expression : public expression {};

template
struct expression {};

struct gives : public expression {};

template void bar(expression);

int main()
{
gives error;
bar(error);
return 0;
}

Actually the reason your code is illegal is because the template argument deduction rules don't distinguish between the direct and indirect base classes of "gives", so there's an ambiguity and deduction fails. The ambiguity in the example above is between expression (direct base class) and expression(indirect baseclass).FWIW, the Gnu compilergives an errortoo.

yeah, continuing the investigation of this problem i came to a very simple test case
here it is

#include 

template struct s;
template<> struct s {};
template<> struct s : public s
{};

struct Int : public s {};

template
void foo(const s&)
{ std::cout << "in foo(const s<" << typeid(type).name() << ">&)n"; }

int main()
{
  Int i;
  foo(i);  //here an error appears
  return 0;
}

i read the standard and found no things that invalidate this code
contrary the standard gives an example like

template
struct s {};

struct a : public s {};

template
void foo(const s&) {}

int main()
{
  a object;
  foo(object);  //calls foo(const s&)
  return 0;
}

and the second thing the standard states is that while picking the best function among oveloaded versions involving conversions
- given class A, B derived from A and C derived from B
- conversion from C* to B* is better than C* to A*,
- conversion from C& to B& is better than C& to A&
which renders the following algorithm for the first piece of code:

- template arguments can obviously be void or int giving function instances
foo(const s&) and
foo(const s&)
- following the rule for overloaded functions (above)we choose the variant
foo(const s&)
because s is the direct base class for Int rather than s

i think that compilers fail to deduce arguments because there are two instances of the same template class in same hierarchy
but if there were only one all goes ok

Quoting - de666

yeah, continuing the investigation of this problem i came to a very simple test case
here it is

#include 

template struct s;
template<> struct s {};
template<> struct s : public s
{};

struct Int : public s {};

template
void foo(const s&)
{ std::cout << "in foo(const s<" << typeid(type).name() << ">&)n"; }

int main()
{
  Int i;
  foo(i);  //here an error appears
  return 0;
}

i read the standard and found no things that invalidate this code
contrary the standard gives an example like

template
struct s {};

struct a : public s {};

template
void foo(const s&) {}

int main()
{
  a object;
  foo(object);  //calls foo(const s&)
  return 0;
}

and the second thing the standard states is that while picking the best function among oveloaded versions involving conversions
- given class A, B derived from A and C derived from B
- conversion from C* to B* is better than C* to A*,
- conversion from C& to B& is better than C& to A&
which renders the following algorithm for the first piece of code:

- template arguments can obviously be void or int giving function instances
foo(const s&) and
foo(const s&)
- following the rule for overloaded functions (above)we choose the variant
foo(const s&)
because s is the direct base class for Int rather than s

i think that compilers fail to deduce arguments because there are two instances of the same template class in same hierarchy
but if there were only one all goes ok

The example in the standard you cited aboveis not applicable since there's only one possible deduction for what the template argument "type" is and that is int. The rules you quoted above apply to choosing between overloaded functions, not template argument deduction. The template argument deduction rules are in section 14.8.2 of the 1998 standard. I see nothing in there that favors a deduction to a direct base class over an indirect base class.

Your last sentence is exactly correct and is what I tried tosay was theprobleminmy earlier note. Choosing between the two instances are ambiguous and that is why template argument deduction (not overloading)fails. The Microsoft compiler is not following the standard.

afaik template functions take part in overload resolution

it is said in the standard before the rules i cited that a set of viable functions is built and an instance of a template function can be a viable function if the template arguments can be deduced

in this case arguments can be deduced in two ways and both instances go to the set of viable functions

then the mentiioned rule applies and function taking reference to the most derived class wins

furthermore all this reasoning is not counterintuitive and a user encountering a pattern like the one above expects just what i described

Quoting - de666

afaik template functions take part in overload resolution

it is said in the standard before the rules i cited that a set of viable functions is built and an instance of a template function can be a viable function if the template arguments can be deduced

in this case arguments can be deduced in two ways and both instances go to the set of viable functions

then the mentiioned rule applies and function taking reference to the most derived class wins

furthermore all this reasoning is not counterintuitive and a user encountering a pattern like the one above expects just what i described

As explained in the Microsoft documentation here:

http://msdn.microsoft.com/en-us/library/s016dfe8.aspx

Note that it says that if template argument deduction fails then the potential specializations resulting fromthe deduction of that function templateare not added to the overload resolution set of viable functions.

I'm not going to argue that this behaviour might be non-intuitive. If you feel strongly about it you should probably submit an issue to the C++ standards committee.

Judy

you are absolutely right in that part about deduction fail and further consequences
i even won't try to argue about it

my question is: why does the template argument deduction fail?
because the template arguments in the lastcode pieceare obviously either void or int
at least it must be int because s is the direct base class of class a

i see the forum has been modified and i'm afraid this thread is lost

so iremind you and --are we going to get at the heart of the matter?

Leave a Comment

Please sign in to add a comment. Not a member? Join today