Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is this template parsing conflict called?

I am getting an issue compiling this minimal example with g++ 7.3

template<typename T>
struct conflict
{
};

template<typename T>
struct s
{
    int conflict;
};

template<typename T>
bool go()
{
    s<T>* sp;
    return sp->conflict < 0;
}

The actual error message is less than revealing:

|| test.cpp: In function ‘bool go()’:
test.cpp|16 col 24| error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> struct conflict’
||   return sp->conflict < 0;
||                         ^
test.cpp|16 col 24| note:   expected a type, got ‘0’

In truth the compiler is trying to instantiate the conflict template instead of comparing the conflict field.

Does this error have a name?

Also, I fixed it by swapping the comparison to use >. Is there a better way?

like image 710
Nate Avatar asked Dec 05 '18 19:12

Nate


People also ask

What is conflict in parsing?

There are two kinds of conflicts that can occur in an SLR(1) parsing table. A shift-reduce conflict occurs in a state that requests both a shift action and a reduce action. A reduce-reduce conflict occurs in a state that requests two or more different reduce actions.

What is RR conflict in compiler design?

A Reduce-Reduce error is a caused when a grammar allows two or more different rules to be reduced at the same time, for the same token. When this happens, the grammar becomes ambiguous since a program can be interpreted more than one way. This error can be caused when the same rule is reached by more than one path.


1 Answers

As T.C. pointed out this is the subject of CWG active issue 1835 which says:

According to 6.4.5 [basic.lookup.classref] paragraph 1,

In a class member access expression (8.2.5 [expr.ref]), if the . or -> token is immediately followed by an identifier followed by a <, the identifier must be looked up to determine whether the < is the beginning of a template argument list (17.2 [temp.names]) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template.

Given

   template<typename T> T end(T);
   template<typename T>
   bool Foo(T it) {
     return it->end < it->end;
   }

since it is dependent and thus end cannot be looked up in the class of the object expression, it is looked up in the context of the postfix-expression. This lookup finds the function template, making the expression ill-formed.

One possibility might be to limit the lookup to the class of the object expression when the object expression is dependent.

A fix is to use ():

return (sp->conflict) < 0;

see it live on godbolt

like image 115
Shafik Yaghmour Avatar answered Oct 04 '22 05:10

Shafik Yaghmour