C++ syntax ambiguity - c++

Consider:
void f(std::pair<bool,bool> terms = std::pair<bool,bool>(1,1)) {}
gcc 4.4 is ok, gcc 4.3 complains error: expected ',' or '...' before '>' token. The fix is:
void f(std::pair<bool,bool> terms = (std::pair<bool,bool>(1,1))) {}
What's the reason? Is it a bug in 4.3?

This was a known issue. It thinks that the second comma separates parameter declarations. This comes from the fact that in a class definition, function default arguments are first only tokenized, and then only later parsed when the full class body has been read. As it thus doesn't really parse the default argument, it doesn't notice the comma is really a comma within a template argument list instead.
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#325 for something to read about it. Cited
The other problem is with collecting the tokens that form the default argument expression. Default arguments which contain template-ids with more than one parameter present a difficulty in determining when the default argument finishes. Consider,
template <int A, typename B> struct T { static int i;};
class C {
int Foo (int i = T<1, int>::i);
};
The default argument contains a non-parenthesized comma. Is it required that this comma is seen as part of the default argument expression and not the beginning of another of argument declaration? To accept this as part of the default argument would require name lookup of T (to determine that the '<' was part of a template argument list and not a less-than operator) before C is complete. Furthermore, the more pathological
class D {
int Foo (int i = T<1, int>::i);
template <int A, typename B> struct T {static int i;};
};
would be very hard to accept. Even though T is declared after Foo, T is in scope within Foo's default argument expression.

Related

c++ template structure about iterator_traits

I'm studying about iterator and I found some source code on github.
I realize what this code do but cannot find how.
template <class T>
struct _has_iterator_category
{
private:
struct _two { char _lx; char _lxx; };
template <class U> static _two _test(...);
template <class U> static char _test(typename U::iterator_category * = 0);
public:
static const bool value = sizeof(_test<T>(0)) == 1;
};
I think this code check if T has iterator_category, but I cannot figure few things about how and why this works.
Why this code use two template? what class U template does?
Is _test(...) function or constructor? And what is (...) means?
2-1. If _test is function, is this code doing function overloading? then how can be overloaded with different return type?
2-2. If _test is constructor, then is char a class in c++?
What does * = operator do in (typename U::iterator_category * = 0)? Is it multiplying iterator_category or make 0 of iterator_category pointer?
what sizeof(_test<T>(0)) == 1; means? Is it return true if sizeof(_test<T>(0)) is 1?
I searched a lot of document for iterator_traits and other things, but failed to interpret this code.
First thing first, this code is completely interpretable on it's own, if you know C++. No documentation on external components is required. It's not depending on anything. You have asked questions which suggest some gaps in basic C++ syntax understanding.
1. Template definition _test is a template member of class template _has_iterator_category. It's a template defined within template, so even if you instantiate _has_iterator_category, you still have to instantiate _test later, it got a separate template parameter.
2. Technically, it's neither. Because a class template isn't a type and a function template, which _test is, is not a function.
Constructor's name always matched the most nested enclosing class scope, i.e. _has_iterator_category in here. _has_iterator_category doesn't have a constructor declared.
It's a template of function. There are two templates, for different arguments, with different argument type. If both templates can be instantiated through successful substitution of U with concrete type, the function is overloaded.
3. It's not operator * =, operators cannot have a whitespace in them. It's * and =. This is a nameless version of argument list which could be written otherwise:
template <class U> static char _test(typename U::iterator_category *arg = 0);
= 0 is default value of function parameter arg. As arg is not being used in this context, its name can be skipped.
The single parameter of function's signature got type U::iterator_category *. typename is a keyword required by most but recent C++ standards for a nested type dependant on template parameter. This assumes that U must have a nested type
iterator_category. Otherwise the substitution of template parameters would fail.
template <class U> static _two _test(...);
Here function signature is "variadic". It means that function may take any number of arguments after substitution of template parameters. Just like printf.
4. sizeof(_test<T>(0)) == 1 equals to true if size of _test<T>(0) result is equal to 1.
The whole construction is a form of rule known as SFINAE - Substitution Failure Is Not An Error. Even if compiler fails to substitute one candidate, it would still try other candidates. The error would diagnosed when all options are exhausted.
In this case the expression sizeof(_test<T>(0)), which attempts to substitute U with T. It's the reason why _test is made into a nested template. The class is valid, but now we check the function.
If type-id T::iterator_category is valid, then substitution will be successful, as the resulting declaration will be valid. _test(...) can be successful too, but then we go to overload choice rules.
A variadic argument always implies type conversion, so there is no ambiguity and _test(...) will be discarded.
If T::iterator_category is not a valid type, _two _test(...) is the only instance of _test().
Assuming that sizeof(char) equals to 1, the constant value is initialized with true if return value of expression would be _test<T>(0) got same size as char. Which is only true if T::iterator_category exists.
Essentially this constructs checks, if class T contains nested type T::iterator_category in somewhat clumsy and outdated ways. But it is compatible with very early C++ standards as it doesn't use nullptr or <type_traits> header.

Inheriting templated operator= in C++14: different behaviour with g++ and clang++

I have this code which works as expected with GCC 9.1:
#include <type_traits>
template< typename T >
class A
{
protected:
T value;
public:
template< typename U,
typename...,
typename = std::enable_if_t< std::is_fundamental< U >::value > >
A& operator=(U v)
{
value = v;
return *this;
}
};
template< typename T >
class B : public A<T>
{
public:
using A<T>::operator=;
template< typename U,
typename...,
typename = std::enable_if_t< ! std::is_fundamental< U >::value > >
B& operator=(U v)
{
this->value = v;
return *this;
}
};
int main()
{
B<int> obj;
obj = 2;
}
(In practice we would do something fancy in the B::operator= and even use different type traits for enable_if, but this is the simplest reproducible example.)
The problem is thtat Clang 8.0.1 gives an error, somehow the operator= from the parent class is not considered, although the child has using A<T>::operator=;:
test.cpp:39:9: error: no viable overloaded '='
obj = 2;
~~~ ^ ~
test.cpp:4:7: note: candidate function (the implicit copy assignment operator) not viable:
no known conversion from 'int' to 'const A<int>' for 1st argument
class A
^
test.cpp:4:7: note: candidate function (the implicit move assignment operator) not viable:
no known conversion from 'int' to 'A<int>' for 1st argument
class A
^
test.cpp:20:7: note: candidate function (the implicit copy assignment operator) not
viable: no known conversion from 'int' to 'const B<int>' for 1st argument
class B : public A<T>
^
test.cpp:20:7: note: candidate function (the implicit move assignment operator) not
viable: no known conversion from 'int' to 'B<int>' for 1st argument
class B : public A<T>
^
test.cpp:28:8: note: candidate template ignored: requirement
'!std::is_fundamental<int>::value' was not satisfied [with U = int, $1 = <>]
B& operator=(U v)
^
1 error generated.
Which compiler is right according to the standard? (I'm compiling with -std=c++14.) How should I change the code to make it correct?
Consider this simplified code:
#include <iostream>
struct A
{
template <int n = 1> void foo() { std::cout << n; }
};
struct B : public A
{
using A::foo;
template <int n = 2> void foo() { std::cout << n; }
};
int main()
{
B obj;
obj.foo();
}
This prints 2 as it should with both compilers.
If the derived class already has one with the same signature, then it hides or overrides the one brought in by the using declaration. The signatures of your assignment operators are ostensibly the same. Consider this fragment:
template <typename U,
typename = std::enable_if_t<std::is_fundamental<U>::value>>
void bar(U) {}
template <typename U,
typename = std::enable_if_t<!std::is_fundamental<U>::value>>
void bar(U) {}
This causes a redefinition error for bar with both compilers.
HOWEVER if one changes the return type in one of the templates, the error goes away!
It's time to look at the standard closely.
When a using-declarator brings declarations from a base class into a derived class, member functions and
member function templates in the derived class override and/or hide member functions and member function
templates with the same name, parameter-type-list (11.3.5), cv-qualification, and ref-qualifier (if any) in
a base class (rather than conflicting). Such hidden or overridden declarations are excluded from the set of
declarations introduced by the using-declarator
Now this sounds dubious as far as templates are concerned. How could one even compare two parameter type lists without comparing template parameter lists? The former depends on the latter. Indeed, a paragraph above says:
If a function declaration in namespace scope or block scope has the same name and the same parameter-type-list (11.3.5) as a function introduced by a using-declaration, and the declarations do not declare the
same function, the program is ill-formed. If a function template declaration in namespace scope has the same
name, parameter-type-list, return type, and template parameter list as a function template introduced by a
using-declaration, the program is ill-formed.
This makes much more sense. Two templates are the same if their template parameter lists are the same, along with everything else... but wait, this includes the return type! Two templates are the same if their names and everything in their signatures, including the return types (but not including default parameter values) is the same. Then one can conflict with or hide the other.
So what happens if we change the return type of the assignment operator in B and make it the same as in A? GCC stops accepting the code.
So my conclusion is this:
The standard is unclear when it comes to templates hiding other templates brought by using declarations. If it meant to exclude template parameters from comparison, it should have said so, and clarify the possible implications. For example, can a function hide a function template, or vise versa? In any case there's an unexplained inconsistency in the standard language between using in namespace scope and using that brings base class names to the derived class.
GCC seems to take the rule for using in namespace scope and apply it in the context of base/derived class.
Other compilers do something else. It is not too clear what exactly; possibly compare the parameter type lists without considering the template parameters (or return types), as the letter of the standard says, but I'm not sure this makes any sense.
Note: I feel that this answer is wrong and n.m.'s answer is the correct one. I
will keep this answer because I am not sure, but please go and check
that answer.
Per [namespace.udecl]/15:
When a using-declaration brings names from a base class into a
derived class scope, member functions and member function templates in
the derived class override and/or hide member functions and member
function templates with the same name, parameter-type-list
([dcl.fct]), cv-qualification, and ref-qualifier (if any) in a base
class (rather than conflicting).
The operator= declared in the derived class B has exactly the same name, parameter-type-list, cv-qualification (none), and ref-qualifier (none) as the one declared in A. Therefore, the one declared in B hides the one in A, and the code is ill-formed because overload resolution does not find an appropriate function to call. However, template parameter lists are not addressed here.
So should they be considered? This is where the standard becomes unclear. A and B are considered to have the same (template) signature by Clang, but not by GCC. n.m.'s answer points out that the real issue actually lies on the return type. (Default template arguments are never considered when determining a signature.)
Note that this is decided on name lookup. Template argument deduction is not carried out yet, and neither is substitution. You can't say "oh, deduction / substitution failed, so let's go add more members to the overload set". So SFINAE doesn't make a difference here.

Is it really impossible to skip template parameters with default arguments in C++, why does syntax suggest otherwise?

I've been trying to find a way to skip a template parameter not located at the end of the template parameter list, in a derived class that has been assigned a default in its base class.
I've done some research on this topic, also here on SO. While similar questions have been discussed on SO - many answers basically suggesting it doesn't work were related to very special cases like the hash map case here. Also I found this answer by "Potatoswatter", which in my opinion contradicts the impossibility of skipping such a parameter. In his answer he claims this declaration would be valid:
template< class A, class B = int, class C >
class X;
Assuming it is true that a template parameter may not be skipped (unless at the end of the argument list) such a declaration would make no sense at all. Since B is assigned a default value, but followed by C which has no default, in this case value B would always have to be assigned explicitly, rendering the assignment of int as default for B completely useless. The only scenario where the declaration of X above would make sense is one where one of the following declarations of Y would be valid:
class Y : public X<double, , const std::string&> { ... }
class Y : public X<A = double, C = const std::string&> { ... }
So is it really impossible to skip a template parameter that is not located at the end of the template parameter list when deriving a specialized class?
If it is impossible why so, and why does legal syntax apparently suggest otherwise (see class X example above)?
If it is in fact not impossible, how can one skip a template argument that has been assigned a default?
The relevant standardese is contained in "Template Parameters [temp.param]" (14.1).
Essentially, a default argument may only be used if the parameter to which it applies is not followed by any non-pack parameters that do not have default arguments ([temp.param]/11). However, the syntax you quoted is usable in a declaration in the situation described by [temp.param]/10:
The set of default template-arguments available for use is obtained by merging the default arguments from
all prior declarations of the template in the same way default function arguments are (8.3.6). [Example:
template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;
is equivalent to
template<class T1 = int, class T2 = int> class A;
— end example]
The word "class" is kind of hidden in your question, so I thought I'd mention (even though this isn't exactly an answer) that template parameters with defaults can be "skipped", sort of, in calls to function templates. Consider this code:
template<class X, class Y = int, class Z>
void foo(X x, Y y, Z z) {
(void)x, (void)y, (void)z;
puts(__PRETTY_FUNCTION__);
}
int main()
{
foo(3.14, {}, 1.45f);
}
Template parameter X is deduced as double (and the default, if any, would go unused).
Template parameter Y cannot be deduced in this call, so the default of int is used.
Template parameter Z is deduced as float.
Providing defaults for function template parameters happens a lot in the STL these days because of the undeduceability of {} in a function argument list. See for example std::exchange or constructor #8 of std::optional.
You might expect that a similar trick could be used with constructor template argument deduction in C++17, but my experimentation suggests that this is not the case. In class template definitions, the compiler will produce a diagnostic if you put a template-parameter-with-default earlier in the list than a template-parameter-without-default.
template<class X, class Y = int, class Z> // error!
struct Foo {};

Why does this dependent name lookup find a global identifier instead of the method?

When the compiler tries to resolve i.template hi<T>(); it finds hi in the global namespace instead of the method hi on i (ideone). Why?
#include <cstdio>
// Define 'hi' and 'bye' in the global namespace; these should *not* be used
template<typename T> struct hi { };
template<typename T> struct bye { };
// Foo needs to be templated for Foo::Inner to be a dependent type (I think)
template<typename T>
struct Foo
{
struct Inner {
// This is a plain-old templated member function of Inner, yes?
template<typename U>
void hi() { std::printf("hi!\n"); }
// This is a plain-old member function of Inner
void bye() { std::printf("bye!\n"); }
};
void sayStuff()
{
Inner i;
i.template hi<T>(); // Fails to compile -- finds global hi instead of member
i.bye(); // Compiles fine, finds member
}
};
int main() {
Foo<int> f;
f.sayStuff();
return 0;
}
I'm using g++ 4.9.1/4.9.2 (-std=c++11). The exact error message:
prog.cpp: In member function 'void Foo<T>::sayStuff()':
prog.cpp:19:5: error: invalid use of 'struct hi<T>'
i.template hi<T>();
^
This code works fine with Clang and VS2013, but generates an error in g++ and EDG. But which compilers are right?
Is there any way to resolve this besides changing the name of the member? In my real code, the conflict arises when a type from the std namespace (that's been imported via using namespace std, say) has the same name as one of my member functions. Obviously I'd like my implementation code to be robust and not cause random name clashes in user code.
To the best of my knowledge here's what's going on.
DR228 says:
[Voted into WP at April 2003 meeting.]
Consider the following example:
template<class T>
struct X {
virtual void f();
};
template<class T>
struct Y {
void g(X<T> *p) {
p->template X<T>::f();
}
};
This is an error because X is not a member template; 14.2 [temp.names] paragraph 5 says:
If a name prefixed by the keyword template is not the name of a member template, the program is ill-formed.
In a way this makes perfect sense: X is found to be a template using ordinary lookup even though p has a dependent type. However, I think this makes the use of the template prefix even harder to teach.
Was this intentionally outlawed?
Proposed Resolution (4/02):
Elide the first use of the word "member" in 14.2 [temp.names] paragraph 5 so that its first sentence reads:
If a name prefixed by the keyword template is not the name of a template, the program is ill-formed.
However, in the most current publicly available draft of the C++ standard N4296 the following wording appears in §14.2.5:
A name prefixed by the keyword template shall be a template-id or the name shall refer to a class template. [Note: The keyword template may not be applied to non-template members of class templates. —end note] [Note: As is the case with the typename prefix, the template prefix is allowed in cases where it is not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the -> or . is not dependent on a template-parameter, or the use does not appear in the scope of a template. —end note]
[Example:
template <class T> struct A {
void f(int);
template <class U> void f(U);
};
template <class T> void f(T t) {
A<T> a;
a.template f<>(t); // OK: calls template
a.template f(t); // error: not a template-id
}
template <class T> struct B {
template <class T2> struct C { };
};
// OK: T::template C names a class template:
template <class T, template <class X> class TT = T::template C> struct D { };
D<B<int> > db;
—end example]
This wording sounded similar, but different enough to go digging. I found that in the N3126 draft the wording was changed to this version.
I was able to link this change back to this DR96:
The following is the wording from 14.2 [temp.names] paragraphs 4 and 5 that discusses the use of the "template" keyword following . or -> and in qualified names.
{snip}
The whole point of this feature is to say that the "template" keyword is needed to indicate that a "<" begins a template parameter list in certain contexts. The constraints in paragraph 5 leave open to debate certain cases.
First, I think it should be made more clear that the template name must be followed by a template argument list when the "template" keyword is used in these contexts. If we don't make this clear, we would have to add several semantic clarifications instead. For example, if you say "p->template f()", and "f" is an overload set containing both templates and nontemplates: a) is this valid? b) are the nontemplates in the overload set ignored? If the user is forced to write "p->template f<>()" it is clear that this is valid, and it is equally clear that nontemplates in the overload set are ignored. As this feature was added purely to provide syntactic guidance, I think it is important that it otherwise have no semantic implications.
Essentially, the very subtle change of DR228 was lost during a subsequent revision; however, because no similar restriction was placed the intent of DR228 probably still holds unless there's been another revision in the standard. This means that template lookup has to occur globally in this case, even though it's a dependent type.
Let's look at our name lookup rules §3.4.5.1:
In a class member access expression (5.2.5), 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 (14.2) 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.
This seems to explicitly state that in baz.foo->template bar<T>(); We will first look in the class context, this includes standard template lookup. After that is done and if nothing is found, if the form of the expression is correct we jump to the context of the entire expression. In essence, it has been promoted and the lookup for that name must perform the same way if the line just read template bar<T>(); Really though we already knew this from DR228. I just wanted to double check and confirm. The real question is which template ought to get priority, the one in the global scope or the one in the class scope.
For that we now need to ask unqualified name lookup, because now bar is being considered in the same context as foo, so it's no longer following member lookup rules, it's following normal, unqualified template lookup rules, which, naturally, prefer the local version.
So in summation, it seems that Clang and MSVC exhibit correct behavior, and GCC and EDG do not in this instance.
My best guess as to why GCC has it wrong is choosing the wrong context to assign to the expression after the rule is triggered. Instead of placing the context at the same level as the postfix-expression it may be just placing it at in the global level on accident? Maybe it simply skips the first lookup step? (But this is merely speculation, I'd have to actually figure out where to look in the GCC source to say.) This would also explain why #Mikael Persson's solution of changing the lookup to a qualified one caused the compile to start again.
The linked bug report from the asker has people talking about why the global scope must be considered, and it ought to be, but it seems pretty straight forward that a local scope match must be given higher priority than the global one. It also seems like there's been a bit of activity there recently.

Why does this default function argument cause the parser to fail? [duplicate]

Yesterday I ran into a g++ (3.4.6) compiler problem for code that I have been compiling without a problem using the Intel (9.0) compiler. Here's a code snippet that shows what happened:
template<typename A, typename B>
class Foo { };
struct Bar {
void method ( Foo<int,int> const& stuff = Foo<int,int>() );
};
The g++ compiler error is:
foo.cpp:5: error: expected `,' or `...' before '>' token
foo.cpp:5: error: wrong number of template arguments (1, should be 2)
foo.cpp:2: error: provided for `template<class A, class B> struct Foo'
foo.cpp:5: error: default argument missing for parameter 2 of `void Bar::method(const Foo<int, int>&, int)'
Apparently, the default argument is not accepted when written this way, and the compiler assumes that instead of the second template argument a new function argument is specified, for which it then expects a default value because the stuff argument has one. I can help the compiler by creating a typedef, and then everything compiles fine:
template<typename A, typename B>
class Foo { };
struct Bar {
typedef Foo<int,int> FooType;
void method ( FooType const& stuff = FooType() );
};
So I can solve my problem, but I don't understand what is going on. Do I miss a C++ (template?) language feature here and am I doing something wrong, or is the g++ compiler wrong in not accepting the first piece of code?
Note BTW that this also compiles ...
template<typename A, typename B>
class Foo { };
void method ( Foo<int,int> const& stuff = Foo<int,int>() );
I am not so sure that this is a bug in g++ (since version 4.2.4). The code now passes in g++ 4.4 (see UPDATE below). In order to have this code compile for other versions of compilers you can add a set of parenthesis around the default argument:
template<typename A, typename B>
class Foo { };
struct Bar {
void method ( Foo<int,int> const& stuff = ( Foo<int,int>() ) );
};
IMO, these parenthesis are necessary as there is an additional requirement that the default argument can refer to a member of the class that may be declared later in the class body:
struct Bar {
void method ( int i = j); // 'j' not declared yet
static const int j = 0;
};
The above code is legal, and when the declaration for 'method' is being parsed the member 'j' has not yet been seen. The compiler therefore can only parse the default argument using syntax checking only, (ie. matching parenthesis and commas). When g++ is parsing your original declaration, what it is actually seeing is the following:
void method ( Foo<int,int> const& stuff = Foo<int // Arg 1 with dflt.
, int>() ); // Arg 2 - syntax error
Adding the extra set of parenthesis ensures that the default argument is handled correctly.
The following case shows an example where g++ succeeds but Comeau still generates a syntax error:
template<int J, int K>
class Foo { };
struct Bar {
void method ( Foo<0, 0> const & i = ( Foo<j, k> () ) );
static const int j = 0;
static const int k = 0;
};
EDIT:
In response to the comment: "You could just as well have a function call with multiple arguments there", the reason that this does not cause a problem is that the comma's inside the function call are surrounded in parenthesis:
int foo (int, int, int);
struct Bar {
void method ( int j =
foo (0, 0, 0) ); // Comma's here are inside ( )
};
It is possible therefore, to parse this using the syntax of the expression only. In C++, all '(' must be matched with ')' and so this is easy to parse. The reason for the problem here is that '<' does not need to be matched, since it is overloaded in C++ and so can be the less than operator or the start of a template argument list. The following example shows where '<' is used in the default argument and implies the less than operator:
template<int I, int J>
class Foo { };
struct Bar {
template <typename T> struct Y { };
void method ( ::Foo<0,0> const& stuff = Foo<10 , Y < int > = Y<int>() );
struct X {
::Foo<0, 0> operator< (int);
};
static X Foo;
};
The above "Foo<10" is a call to the "operator<" defined in 'X', not the start of the template argument list. Again, Comeau generates syntax errors on the above code and g++ (including 3.2.3) parse this correctly.
FYI, the appropriate references are a note in 8.3.6/5:
[Note: in member function declarations, names in default argument expressions are looked
up as described in 3.4.1...
and then in 3.4.1/8
A name used in the definition of a member function (9.3) of class X following the function’s declaratorid29)
shall be declared in one of the following ways:
...
— shall be a member of class X or be a member of a base class of X (10.2), or
This bullet here, is the part that forces the compiler to "delay" lookup for the meaning of the default argument until all of the class members have been declared.
<UPDATE>
As pointed out by "Employed Russian", g++ 4.4 is now able to parse all of these examples. However, until the DR has been addressed by the C++ standards committee I am not yet ready to call this a "bug". I believe that long term extra parenthesis will be required to ensure portability to other compilers/tools (and maybe even future versions of g++).
It has been my experience that the C++ standard does not dictate that compiler vendors should all use the same parser technology and they also cannot expect that all technologies are equally powerful. As a result, parsing requirements normally don't require that vendors perform superhuman feats. To illustrate this consider the following two examples:
typedef T::TYPE TYPE;
T::TYPE t;
If 'T' is dependent, then given each context 'TYPE' must be a typename, however the standard still requires the typename keyword. These examples are unambiguous and can only mean one thing, however the standard (in order to allow for all parser technologies) still requires the typename keyword.
It's possible that the DR may be addressed in such a way that a compiler which fails to parse these examples will still be "standard conforming" as long as extra parenthesis allows the code to parse.
</UPDATE>
This is a known bug in gcc.
It has been fixed in gcc-4.4, which compiles the original source just fine.
Looks like a compiler bug. I tried it on IBM's xlC compiler V7.0 (which I've found to be more standard-conforming than gcc) and it compiles okay.
template <bool> class A {};
typedef A<static_cast<bool>(1>0)> B;//buggy
int main() { B b; }