why can I test for is_volatile<T> but I can't test for is_unsigned<T>?

  • Thread starter Robert Allan Schwartz
  • Start date
R

Robert Allan Schwartz

Why do I get a syntax error below?

I don't see why volatile works but unsigned does not work.

I'm not looking for an answer of the form, "Because the Standard says
so", or "Because the C++ grammer says so"; I'm looking for an
explanation of *why* the Standard and/or the grammar say so.

Thanks,

Robert Schwartz




#include <iostream>

template <typename T>
class is_volatile/*<T>*/
{ public: static const bool value = false; };

template <typename T>
class is_volatile<volatile T>
{ public: static const bool value = true; };

template <typename T>
void test1(void)
{
std::cout << is_volatile<T>::value << std::endl;
}

template <typename T>
class is_unsigned/*<T>*/
{ public: static const bool value = false; };

template <typename T>
class is_unsigned<unsigned T> // "syntax error before '>' token" on
this line.
{ public: static const bool value = true; };

template <typename T>
void test2(void)
{
std::cout << is_unsigned<T>::value << std::endl;
}

int main(void)
{
test1<volatile int>();

test2<unsigned int>();

return 0;
}
 
R

red floyd

Robert said:
Why do I get a syntax error below?

I don't see why volatile works but unsigned does not work.

I'm not looking for an answer of the form, "Because the Standard says
so", or "Because the C++ grammer says so"; I'm looking for an
explanation of *why* the Standard and/or the grammar say so.
IANALG but I think that unsigned is part of the type itself rather than
a qualifier.
Since there are only three (maybe four) unsigned types, why not do the
below:
#include <iostream>

template <typename T>
class is_volatile/*<T>*/
{ public: static const bool value = false; };

template <typename T>
class is_volatile<volatile T>
{ public: static const bool value = true; };

template <typename T>
void test1(void)
{
std::cout << is_volatile<T>::value << std::endl;
}

template <typename T>
class is_unsigned/*<T>*/
{ public: static const bool value = false; };

template <typename T>
class is_unsigned<unsigned T> // "syntax error before '>' token" on
this line.
{ public: static const bool value = true; };


template <>
class is_unsigned<unsigned char>
{ public: static const bool value = true; };

#ifdef UNSIGNED_INT_IS_A_DISTINCT_TYPE_
template <>
class is_unsigned<unsigned int> // not sure if this is needed
this line.
{ public: static const bool value = true; };
#endif

template <>
class is_unsigned<unsigned short>
this line.
{ public: static const bool value = true; };

template <>
class is_unsigned<unsigned long>
this line.
{ public: static const bool value = true; };

#ifdef UNSIGNED_LONG_LONG_IS_DEFINED_BY_THE_COMPILER_
template <>
class is_unsigned<unsigned long long>
this line.
{ public: static const bool value = true; };
#endif
 
A

Ali Cehreli

I don't see why volatile works but unsigned does not work.

As noted by other(s), volatile (like const) is a type
qualifier. 'unsigned' is a part of the type.
template <typename T>
class is_unsigned/*<T>*/
{ public: static const bool value = false; };

You can implement is_unsigned in terms of std::numeric_limits:

#include <iostream>
#include <limits>

int main(void)
{
std::cout << std::numeric_limits<int>::is_signed << '\n';
}

Ali
 
R

Robert Allan Schwartz

I understand that there is another way to implement is_unsigned<T>.
I understand that 'volatile' is a qualifier and 'unsigned' is part of
the type.
What I want to know is, why can I ask type questions of the form
'is_[qualifier]<T>', but I cannot ask type questions of the form
'is_[part_of_type]<T>'?
Did the Standards Committee decide to allow the former and disallow
the latter?
Is this simply an artifact of the grammar?
I'm looking for a deeper explanation.
Anyone got one?

Thanks,

Robert
 
K

Kai-Uwe Bux

Robert said:
I understand that there is another way to implement is_unsigned<T>.
I understand that 'volatile' is a qualifier and 'unsigned' is part of
the type.
What I want to know is, why can I ask type questions of the form
'is_[qualifier]<T>', but I cannot ask type questions of the form
'is_[part_of_type]<T>'?
Did the Standards Committee decide to allow the former and disallow
the latter?
Is this simply an artifact of the grammar?
I'm looking for a deeper explanation.
Anyone got one?

It is the grammar. You should consider it an accident that the typename
"unisgned int" consists of two words. After lexical analysis in the
compiler, very likely, this name becomes just one token. This is, when
the compiler deals with all the template magic, the information you want
is lost already.

What you are trying to do is like writing a template that tests whether a
typename starts with the letter "i".

However, since "unsigned" is not a qualifier, there are no user-defined
types that are unsigned or signed. Thus your template is meaningfull only
for a small number of basic types. For these you can provide specializations
and that way build is_unsigned<T> so that it checks true for the unsigned
basic types. But then, again, this has been done already in numeric_limits.


Best

Kai-Uwe
 
J

Jonathan Turkanis

Robert Allan Schwartz said:
I understand that there is another way to implement is_unsigned<T>.
I understand that 'volatile' is a qualifier and 'unsigned' is part of
the type.
What I want to know is, why can I ask type questions of the form
'is_[qualifier]<T>', but I cannot ask type questions of the form
'is_[part_of_type]<T>'?

You can ask both types of questions, as the responses to your post
have shown.
Did the Standards Committee decide to allow the former and disallow
the latter?
Is this simply an artifact of the grammar?
I'm looking for a deeper explanation.

What we need is a deeper explanation of you question.

Jonathan
 
R

Robert Allan Schwartz

Let me try to refine my question.

In many cases, I can ask if a type is composed of two parts: a token
(e.g. * or &) or a keyword (e.g. const or volatile), followed by
another type.

I can ask if a type is "pointer to T".
I can ask if a type is "reference to T".
I can ask if a type is "const T".
I can ask if a type is "volatile T".
I cannot ask if a type is "unsigned T".
^^^

This appears to be an asymmetry.

Why is there an asymmetry?

I understand that there is another way to ask is_unsigned<T>. That
does not answer my question.
I understand that 'volatile' is a qualifier and 'unsigned' is not.
That does not answer my question.

Thanks,

Robert

Jonathan Turkanis said:
Robert Allan Schwartz said:
I understand that there is another way to implement is_unsigned<T>.
I understand that 'volatile' is a qualifier and 'unsigned' is part of
the type.
What I want to know is, why can I ask type questions of the form
'is_[qualifier]<T>', but I cannot ask type questions of the form
'is_[part_of_type]<T>'?

You can ask both types of questions, as the responses to your post
have shown.
Did the Standards Committee decide to allow the former and disallow
the latter?
Is this simply an artifact of the grammar?
I'm looking for a deeper explanation.

What we need is a deeper explanation of you question.

Jonathan
 
M

Marco Manfredini

Robert said:
Let me try to refine my question.

In many cases, I can ask if a type is composed of two parts: a token
(e.g. * or &) or a keyword (e.g. const or volatile), followed by
another type.

I can ask if a type is "pointer to T".
I can ask if a type is "reference to T".
I can ask if a type is "const T".
I can ask if a type is "volatile T".
I cannot ask if a type is "unsigned T".
^^^

This appears to be an asymmetry.

You can view this as a crack in the *lexical* structure of C++.
"unsigned int" should rather be "unsigned_int" but for compatibility
reasons to C they kept it the other way. Now, since the thing is only
an entity of the lexical structure, you must understand, that for the
compiler "unsigned int" actually reads as "unsigned_int", the parser
might get an appropriate token from the lexical scanner..."unsigned T"
can't be understood, because the comprehension would need to happen at
a semantic level (where T is identified as a type) -- on a lexical
level it doesn't make sense and will never make it into the parser.

Okay, the ones in charge could have promoted "unsigned" out of the
lowland of lexical scanning to the semantic pastures (just to correct
the unpleasant visual artifact) but that would have made everything
much more complicated: every part that deals with cv-qualifiers would
be forced to care for the completely uninteresting, dull and usually
(except for a couple of primitive cases) inapplicable case of
"unsigned". An extra qualifier would burden the user as well. For
example, if you want to do something like "remove_qualifier" you'll
have to check 4 different combinations of qualifiers, adding unsigned
would make you have 8 cases to check!! Qualifiers multiply the number
of possible qualifiers Types, so it's better to keep only the useful
ones. Read this as: We really don't need "unsigned T", thus we don't
commit anybody to parse it.

Marco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top