Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #70297 > unrolled thread

enum type in template declaration

Started bySoviet_Mario <SovietMario@CCCP.MIR>
First post2019-12-05 23:20 +0100
Last post2019-12-07 18:57 +0100
Articles 15 — 6 participants

Back to article view | Back to comp.lang.c++


Contents

  enum type in template declaration Soviet_Mario <SovietMario@CCCP.MIR> - 2019-12-05 23:20 +0100
    Re: enum type in template declaration James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-12-05 22:39 -0500
      Re: enum type in template declaration Soviet_Mario <SovietMario@CCCP.MIR> - 2019-12-06 13:15 +0100
        Re: enum type in template declaration Paavo Helde <myfirstname@osa.pri.ee> - 2019-12-06 14:42 +0200
          Re: enum type in template declaration Soviet_Mario <SovietMario@CCCP.MIR> - 2019-12-06 17:20 +0100
            Re: enum type in template declaration Paavo Helde <myfirstname@osa.pri.ee> - 2019-12-06 20:29 +0200
              Re: enum type in template declaration Soviet_Mario <SovietMario@CCCP.MIR> - 2019-12-06 22:42 +0100
                Re: enum type in template declaration Paavo Helde <myfirstname@osa.pri.ee> - 2019-12-07 00:51 +0200
                  Re: enum type in template declaration Soviet_Mario <SovietMario@CCCP.MIR> - 2019-12-07 18:54 +0100
        Re: enum type in template declaration Öö Tiib <ootiib@hot.ee> - 2019-12-06 06:00 -0800
        Re: enum type in template declaration James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-12-06 09:56 -0500
        Re: enum type in template declaration Manfred <noname@add.invalid> - 2019-12-06 15:56 +0100
    Re: enum type in template declaration Soviet_Mario <SovietMario@CCCP.MIR> - 2019-12-06 18:43 +0100
    Re: enum type in template declaration saturnman2008@gmail.com - 2019-12-07 01:53 -0800
      Re: enum type in template declaration Soviet_Mario <SovietMario@CCCP.MIR> - 2019-12-07 18:57 +0100

#70297 — enum type in template declaration

FromSoviet_Mario <SovietMario@CCCP.MIR>
Date2019-12-05 23:20 +0100
Subjectenum type in template declaration
Message-ID<qsbvs3$81l$1@dont-email.me>
since what version of standard, if any, an ENUM type can be 
an argument of a template ?

sth like

enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };


template <RestrictedValues ttVal> class SizedField
{
private:
unsigned char zzArray [ttVal];


public:

etc etc

}


or if the syntax is wrong, how to workaround ?

The goal is to have a template depending on a restricted 
well defined, and known at compile time, set of integral values







-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)

[toc] | [next] | [standalone]


#70299

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-12-05 22:39 -0500
Message-ID<qscii5$5an$1@dont-email.me>
In reply to#70297
On 12/5/19 5:20 PM, Soviet_Mario wrote:
> since what version of standard, if any, an ENUM type can be 
> an argument of a template ?

It has always been possible to use an enumerated type as a template
parameter. There is no special rule giving a enumerated type any
different status from any other type in that regard.

> sth like
> 
> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
> 
> 
> template <RestrictedValues ttVal> class SizedField

However, you're not using an enumerated type as a template argument,
you're using a enumeration value. That is a marginally newer feature of
C++, though I believe that it still pre-dates the first version of the
standard. There is no distinction for this purpose between values of
enumerated type and those of any other integer type.


[toc] | [prev] | [next] | [standalone]


#70303

FromSoviet_Mario <SovietMario@CCCP.MIR>
Date2019-12-06 13:15 +0100
Message-ID<qsdgou$paa$1@dont-email.me>
In reply to#70299
Il 06/12/19 04:39, James Kuyper ha scritto:
> On 12/5/19 5:20 PM, Soviet_Mario wrote:
>> since what version of standard, if any, an ENUM type can be
>> an argument of a template ?
> 
> It has always been possible to use an enumerated type as a template
> parameter.

sorry I'm not sure I have understood

Do you mean to use it as just a VALUE (instancing it) in an 
generic integral parameter, or a proper TYPE-CHECKED 
declaration (so that giving non typed integer value while 
instancing would give a compile error) ?

> There is no special rule giving a enumerated type any
> different status from any other type in that regard.

Uhm ... ok, maybe I have outdated memories :\

> 
>> sth like
>>
>> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
>>
>>
>> template <RestrictedValues ttVal> class SizedField
> 
> However, you're not using an enumerated type as a template argument,
> you're using a enumeration value. 

Mmmm, exactly the point I am misunderstanding. I believed to 
have been able to establish a proper type-checking in that 
declaration.
How instead it should have been written ?
can you correct my example in order to non accept non 
specific-enum integral instancing ?

> That is a marginally newer feature of
> C++, though I believe that it still pre-dates the first version of the
> standard. There is no distinction for this purpose between values of
> enumerated type and those of any other integer type.
> 
> 
> 


-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)

[toc] | [prev] | [next] | [standalone]


#70304

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2019-12-06 14:42 +0200
Message-ID<qsdib1$2j6$1@dont-email.me>
In reply to#70303
On 6.12.2019 14:15, Soviet_Mario wrote:
> Il 06/12/19 04:39, James Kuyper ha scritto:
>> On 12/5/19 5:20 PM, Soviet_Mario wrote:
>>> since what version of standard, if any, an ENUM type can be
>>> an argument of a template ?
>>
>> It has always been possible to use an enumerated type as a template
>> parameter.
>
> sorry I'm not sure I have understood

A template parameter can be a type, an int, etc. An enum type is also a 
type:

enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };

template<typename T>
class A {
   T member;
};

A<RestrictedValues> x; // OK

Here, an enum type is used as an argument of a template, as you requested.

However, I suspect that you actually want to use an enum value (not enum 
type) as the template parameter - see below.

>
> Mmmm, exactly the point I am misunderstanding. I believed to have been
> able to establish a proper type-checking in that declaration.
> How instead it should have been written ?
> can you correct my example in order to non accept non specific-enum
> integral instancing ?

You have not said what your problem is. If you got a compiler error, 
then what was the code and what was the error?

What you wrote was basically correct syntax (after commenting out "etc 
etc"). This compiles fine:

enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };

template <RestrictedValues ttVal> class SizedField
{
private:
	unsigned char zzArray[ttVal];


public:

	//etc etc

};

int main() {
	SizedField<B> foo;
}

[toc] | [prev] | [next] | [standalone]


#70310

FromSoviet_Mario <SovietMario@CCCP.MIR>
Date2019-12-06 17:20 +0100
Message-ID<qsdv4a$fa2$1@dont-email.me>
In reply to#70304
Il 06/12/19 13:42, Paavo Helde ha scritto:
> On 6.12.2019 14:15, Soviet_Mario wrote:
>> Il 06/12/19 04:39, James Kuyper ha scritto:
>>> On 12/5/19 5:20 PM, Soviet_Mario wrote:
>>>> since what version of standard, if any, an ENUM type can be
>>>> an argument of a template ?
>>>
>>> It has always been possible to use an enumerated type as 
>>> a template
>>> parameter.
>>
>> sorry I'm not sure I have understood
> 
> A template parameter can be a type, an int, etc. An enum 
> type is also a type:
> 
> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
> 
> template<typename T>
> class A {
>    T member;
> };
> 
> A<RestrictedValues> x; // OK
> 
> Here, an enum type is used as an argument of a template, as 
> you requested.
> 
> However, I suspect that you actually want to use an enum 
> value (not enum type) as the template parameter - see below.

none of both : I would like to declare that a parameter must 
be of enum type, so that the values actually received by the 
actual instance are not simply generic integral, but a 
selected subset.

Assume you would like to model a "pixel" with a variable 
depth of color, but that such depth should be checked (at 
compile time) to be a power of two, and set up an enum like

enum EnumDepths { two = 2, four = 4, eight = 8 }

then the template should not take a simple integral 
paramenter, as one could instantiate it wrongly

template <3> class ClsBMPofPixels;

so the typename must be of EnumDepths type, and only after 
this compile time check, yes, then internally the VALUE 
passed is used practically

> 
>>
>> Mmmm, exactly the point I am misunderstanding. I believed 
>> to have been
>> able to establish a proper type-checking in that declaration.
>> How instead it should have been written ?
>> can you correct my example in order to non accept non 
>> specific-enum
>> integral instancing ?
> 
> You have not said what your problem is. If you got a 
> compiler error, then what was the code and what was the error ?

no, still just trying to figure out and think, not yet any 
practical code

> 
> What you wrote was basically correct syntax (after 
> commenting out "etc etc"). This compiles fine:
> 
> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
> 
> template <RestrictedValues ttVal> class SizedField
> {
> private:
>      unsigned char zzArray[ttVal];
> 
> 
> public:
> 
>      //etc etc
> 
> };
> 
> int main() {
>      SizedField<B> foo;
> }
> 

yes but would such code protect me from writing


template <5> class SizedField; ? Would the compiler check 
that 5 is not a legal value of the enum ?

If so, okay ...


Oh, but BTW, what "helper" functions about run-time 
INTROSPECTION are more or less standard ?


I've found some is_enum<EnumType> (), is_array<typename> () 
and so.

But a simple function like : bool is_of_type <typename> ()

in other languages such operators are named like "TypeOf" 
(or typename, also a string representation could be usefull)

This question is for a concrete case.
I'm  trying to build a 2D table container not particularly 
generic : it supports just two type of contained items, 
either double either a "fixed size string", but I'm not sure 
I'd be able to write really generic functions as the two 
basic types contain some equivalent operators, constructors 
and comparison op, but also some semantically different 
accessors for higher level function on a container.

So I'd appreciate some way a container could look inside 
himself (at runtime) and be aware of its type and call 
proper specialized functions where the syntax are not 
equivalent and I cannot rely only on overload for automatic 
selection of the best fit, or even in case I have to choose 
to MIX data, thing that will end in ambiguity, as the two 
types (fixedstrings and double) are largely convertible and 
interchangeable, so a generic function with identical 
signatures could not know what is the best to be called)








-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)

[toc] | [prev] | [next] | [standalone]


#70318

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2019-12-06 20:29 +0200
Message-ID<qse6ma$1j7$1@dont-email.me>
In reply to#70310
On 6.12.2019 18:20, Soviet_Mario wrote:
> Il 06/12/19 13:42, Paavo Helde ha scritto:
>>
>> What you wrote was basically correct syntax (after commenting out "etc
>> etc"). This compiles fine:
>>
>> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
>>
>> template <RestrictedValues ttVal> class SizedField
>> {
>> private:
>>      unsigned char zzArray[ttVal];
>>
>>
>> public:
>>
>>      //etc etc
>>
>> };
>>
>> int main() {
>>      SizedField<B> foo;
>> }
>>
>
> yes but would such code protect me from writing
>
>
> template <5> class SizedField; ? Would the compiler check that 5 is not
> a legal value of the enum ?

Yes, it will check. Why don't you try it out by yourself?

num RestrictedValues { A = 1, B = 2, C = 4, D = 8 };

template <RestrictedValues ttVal> class SizedField
{
private:
	unsigned char zzArray[ttVal];


public:

	//etc etc

};

int main() {
	SizedField<3> foo;
}

1>main.cpp
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(16): error C2440: 
'specialization': cannot convert from 'int' to 'RestrictedValues'
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(16): note: 
Conversion to enumeration type requires an explicit cast (static_cast, 
C-style cast or function-style cast)
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(16): error C2973: 
'SizedField': invalid template argument 'int'
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(4): note: see 
declaration of 'SizedField'

However, 'SizedField<RestrictedValues(3)> foo;' compiles. I would not 
worry about that, in C++ one can always find ways to shoot himself.

>
> If so, okay ...
>
>
> Oh, but BTW, what "helper" functions about run-time INTROSPECTION are
> more or less standard ?
>
>
> I've found some is_enum<EnumType> (), is_array<typename> () and so.
>
> But a simple function like : bool is_of_type <typename> ()
>
> in other languages such operators are named like "TypeOf" (or typename,
> also a string representation could be usefull)

C++ is pretty statically typed, so you typically do not need things like 
TypeOf to find out the type at run time. For polymorphic types there is 
typeid() though which is similar, and also provides name() (which is not 
guaranteed to be useful).

>
> This question is for a concrete case.
> I'm  trying to build a 2D table container not particularly generic : it
> supports just two type of contained items, either double either a "fixed
> size string", but I'm not sure I'd be able to write really generic
> functions as the two basic types contain some equivalent operators,
> constructors and comparison op, but also some semantically different
> accessors for higher level function on a container.
>
> So I'd appreciate some way a container could look inside himself (at
> runtime) and be aware of its type and call proper specialized functions
> where the syntax are not equivalent and I cannot rely only on overload
> for automatic selection of the best fit, or even in case I have to
> choose to MIX data, thing that will end in ambiguity, as the two types
> (fixedstrings and double) are largely convertible and interchangeable,
> so a generic function with identical signatures could not know what is
> the best to be called)

You have to make up your mind if you have the type (double or string) 
fixed at compile time or at run time. If at compile time, then there is 
no need for the container to check the type at run time, as the type was 
already fixed at the compile time and cannot change. E.g. a 
std::vector<double> does not need to check at run-time if its elements 
have suddenly turned into strings.

If the item type only becomes known only at run time, then it most 
probably means you have some variant type. For this custom variant type 
there are no overloaded functions present, you have to write them 
yourself, and there you have to figure out the correct type at run-time 
and act accordingly.

[toc] | [prev] | [next] | [standalone]


#70321

FromSoviet_Mario <SovietMario@CCCP.MIR>
Date2019-12-06 22:42 +0100
Message-ID<qsei0f$7eo$1@dont-email.me>
In reply to#70318
Il 06/12/19 19:29, Paavo Helde ha scritto:
> On 6.12.2019 18:20, Soviet_Mario wrote:
>> Il 06/12/19 13:42, Paavo Helde ha scritto:
>>>
TNX
  (for the 1st part)

> However, 'SizedField<RestrictedValues(3)> foo;' compiles. I 
> would not worry about that, in C++ one can always find ways 
> to shoot himself.

ok, this kind of mistakes worries me less than simple slight

> 
>>
>> If so, okay ...
>>
>>
>> Oh, but BTW, what "helper" functions about run-time 
>> INTROSPECTION are
>> more or less standard ?
>>
>>
>> I've found some is_enum<EnumType> (), is_array<typename> 
>> () and so.
>>
>> But a simple function like : bool is_of_type <typename> ()
>>
>> in other languages such operators are named like "TypeOf" 
>> (or typename,
>> also a string representation could be usefull)
> 
> C++ is pretty statically typed, so you typically do not need 
> things like TypeOf to find out the type at run time. For 
> polymorphic types there is typeid() though which is similar, 
> and also provides name() (which is not guaranteed to be 
> useful).
> 
>>
>> This question is for a concrete case.
>> I'm  trying to build a 2D table container not particularly 
>> generic : it
>> supports just two type of contained items, either double 
>> either a "fixed
>> size string", but I'm not sure I'd be able to write really 
>> generic
>> functions as the two basic types contain some equivalent 
>> operators,
>> constructors and comparison op, but also some semantically 
>> different
>> accessors for higher level function on a container.
>>
>> So I'd appreciate some way a container could look inside 
>> himself (at
>> runtime) and be aware of its type and call proper 
>> specialized functions
>> where the syntax are not equivalent and I cannot rely only 
>> on overload
>> for automatic selection of the best fit, or even in case I 
>> have to
>> choose to MIX data, thing that will end in ambiguity, as 
>> the two types
>> (fixedstrings and double) are largely convertible and 
>> interchangeable,
>> so a generic function with identical signatures could not 
>> know what is
>> the best to be called)
> 
> You have to make up your mind if you have the type (double 
> or string) fixed at compile time or at run time. 

they will exist both, and interact from time to time (mutual 
conversions, plus some calculations done in string mode, 
like dates comparisons and some sorting in names/surnames 
fields, and other in "double mode", statistics on data. The 
two tables have to stay synced when one is sorted and the 
other driven together)

> If at 
> compile time, then there is no need for the container to 
> check the type at run time, as the type was already fixed at 
> the compile time and cannot change. E.g. a 
> std::vector<double> does not need to check at run-time if 
> its elements have suddenly turned into strings.

it is the template function that is generic and has to know 
to cope with both in different semantically ways, or no ?

> 
> If the item type only becomes known only at run time, then 
> it most probably means you have some variant type. 

uhm ... the allocation of proper types is known, but at 
"CODE-TIME" some functions have duplexed code, and must know 
which part to use according to the actual type of the 
container caller.

Maybe this arises from bad design of the functions, dunno :(

anyway I'll study typeid and type_info keywords. Tnx

> For this 
> custom variant type there are no overloaded functions 
> present, you have to write them yourself, and there you have 
> to figure out the correct type at run-time and act accordingly.
> 


-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)

[toc] | [prev] | [next] | [standalone]


#70322

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2019-12-07 00:51 +0200
Message-ID<qsem1j$unb$1@dont-email.me>
In reply to#70321
On 6.12.2019 23:42, Soviet_Mario wrote:
>
> uhm ... the allocation of proper types is known, but at "CODE-TIME" some
> functions have duplexed code, and must know which part to use according
> to the actual type of the container caller.

Sorry, I cannot make heads or tails out of your babble, but as it seems 
you are fascinated by templates and not really comprehending them, here 
are some general remarks about them which might be helpful.

I know this can be confusing, but in C++ it is actually pretty simple: 
templates are a compile-time feature. If you need something to be solved 
by template mechanisms, it must be known at compile time. And vice 
versa, if something is only known only at run-time, you have to do it in 
an old-fashioned run-time way - an if, a switch, etc.

hth

[toc] | [prev] | [next] | [standalone]


#70339

FromSoviet_Mario <SovietMario@CCCP.MIR>
Date2019-12-07 18:54 +0100
Message-ID<qsgp0a$kba$1@dont-email.me>
In reply to#70322
Il 06/12/19 23:51, Paavo Helde ha scritto:
> On 6.12.2019 23:42, Soviet_Mario wrote:
>>
>> uhm ... the allocation of proper types is known, but at 
>> "CODE-TIME" some
>> functions have duplexed code, and must know which part to 
>> use according
>> to the actual type of the container caller.
> 
> Sorry, I cannot make heads or tails out of your babble, but 
> as it seems you are fascinated by templates and not really 
> comprehending them, here are some general remarks about them 
> which might be helpful.
> 
> I know this can be confusing, but in C++ it is actually 
> pretty simple: templates are a compile-time feature. If you 
> need something to be solved by template mechanisms, it must 
> be known at compile time. And vice versa, if something is 
> only known only at run-time, you have to do it in an 
> old-fashioned run-time way - an if, a switch, etc.

yes, in fact the template function which cannot solve one 
aspect, has a switch.
But the control variable of the switch must be evaluated by 
ITS TYPE (or some internal ID, hash or other info associated 
to the type, not its value). In other words it must emulate 
sort of a virtual function selector.

Many other aspect of the generic container using a lot of 
common operators with a homogeneous semantic (assignments, 
overloaded by both, comparisons, idem) are instead managed 
by the container generically.

Indexing like an array but using operator () (row, column) 
instead is semantically different for container<double> and 
container<fixed_string>, the specialized versions do not 
have even the same number of parameters, the latter has a 
third parameter for index of character

I cannot explain well :\
anyway yes, there are lots of aspects of templates I miss to 
understand


> 
> hth
> 


-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)

[toc] | [prev] | [next] | [standalone]


#70305

FromÖö Tiib <ootiib@hot.ee>
Date2019-12-06 06:00 -0800
Message-ID<8d080664-4485-46e6-97fe-c7a51ad395e8@googlegroups.com>
In reply to#70303
On Friday, 6 December 2019 14:15:40 UTC+2, Soviet_Mario  wrote:
> Il 06/12/19 04:39, James Kuyper ha scritto:
> > 
> > However, you're not using an enumerated type as a template argument,
> > you're using a enumeration value. 
> 
> Mmmm, exactly the point I am misunderstanding. I believed to 
> have been able to establish a proper type-checking in that 
> declaration.
> How instead it should have been written ?
> can you correct my example in order to non accept non 
> specific-enum integral instancing ?

We can easily help but right now your descriptions of problem are
too confusing to decipher (at least for me).
Please write compiling example (no pseudocodes) what you want to
achieve. What code compiles (or picks partial specialization that
you don't want it to pick) but you want it not to compile (or to pick
some other specialization).

[toc] | [prev] | [next] | [standalone]


#70307

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-12-06 09:56 -0500
Message-ID<qsdq72$gov$1@dont-email.me>
In reply to#70303
On 12/6/19 7:15 AM, Soviet_Mario wrote:
> Il 06/12/19 04:39, James Kuyper ha scritto:
>> On 12/5/19 5:20 PM, Soviet_Mario wrote:
>>> since what version of standard, if any, an ENUM type can be
>>> an argument of a template ?
>>
>> It has always been possible to use an enumerated type as a template
>> parameter.
> 
> sorry I'm not sure I have understood
> 
> Do you mean to use it as just a VALUE (instancing it) in an 
> generic integral parameter, or a proper TYPE-CHECKED 
> declaration (so that giving non typed integer value while 
> instancing would give a compile error) ?

Neither. I'm talking about a type, not a value. You, on the other hand,
were talking about a value, but referring to it as a type, which is
connected closely to the source of your confusion. I'll explain that in
more detail in my response to your later questions.

>> There is no special rule giving a enumerated type any
>> different status from any other type in that regard.
> 
> Uhm ... ok, maybe I have outdated memories :\

I suspect it's not your memories that are the problem, but your
understanding of the issue.

>>> sth like
>>>
>>> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
>>>
>>>
>>> template <RestrictedValues ttVal> class SizedField
>>
>> However, you're not using an enumerated type as a template argument,
>> you're using a enumeration value. 
> 
> Mmmm, exactly the point I am misunderstanding. I believed to 
> have been able to establish a proper type-checking in that 
> declaration.


There's nothing wrong with that declaration, as such. It just has
nothing to do with the contents of the sentence you started your message
with. What you refer to in that sentence would match the following code:

    #include <vector>
    std::vector<enum RestrictedValues> vrv;

The type "enum RestrictedValues" is allowed as an argument the the
std::vector template class, and that has always been allowed, for as
long as C++ (which wasn't known as C++ yet, at the time this feature was
added) has had templates.

Your code does NOT use a enumerated type as a template argument. It uses
a enumeration value as an argument. ttVall above is example of what is
called a template non-type argument. I believe that those were a
somewhat later addition to the language, but I also believe that they
were already fully supported before I first learned about C++, would
would have been in the late 1980s, well before the first version of the
C++ standard was approved.


The latest draft standard I have is n4659.pdf. Template non-type
arguments are described in section 17.3.2:

> If the type of a template-parameter contains a placeholder type (10.1.7.4, 17.1), the deduced parameter type is
> determined from the type of the template-argument by placeholder type deduction (10.1.7.4.1). If a deduced
> parameter type is not permitted for a template-parameter declaration (17.1), the program is ill-formed.
> A template-argument for a non-type template-parameter shall be a converted constant expression (8.20) of
> the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the
> value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
> (2.1) — a subobject (4.5),
> (2.2) — a temporary object (15.2),
> (2.3) — a string literal (5.13.5),
> (2.4) — the result of a typeid expression (8.2.8), or
> (2.5) — a predefined __func__ variable (11.4.1).

ttVall is type-checked. However, C++ allows the creation of values of
enumerated type that don't match any of the enumeration constants
associated with that type - see 10.2p8 for a precise specification of
the range of values permitted. Your template can therefore be
instantiated with any of those other values, which I suspect is not what
you want.

However, something that might work as you might like is to declare a
template class, but with no definition for that class. Provide explicit
specializations of the template for the particular values you want
supported, which don't use the generic definition. Then any use of the
template that doesn't match one of the specializations will produce an
error message. Here's some simplified example code:

#include <iostream>
enum mybool {FALSE, TRUE};

template <mybool val> struct boolname;

template <> struct boolname<FALSE> {
    const char *name() const { return "False";};
};
template <> struct boolname<TRUE> {
    const char *name() const { return "True";};
};

int main(void)
{
    boolname<FALSE> t;
    std::cout << t.name() << std::endl;
    return 0;
}

If you change the final occurrence of FALSE in that code with
static_cast<mybool>(2), it will fail at compile time with a diagnostic,
because their is no specialization for that value, and no generic
definition of the template that could be used for unspecialized values.

[toc] | [prev] | [next] | [standalone]


#70308

FromManfred <noname@add.invalid>
Date2019-12-06 15:56 +0100
Message-ID<qsdq77$1pk1$1@gioia.aioe.org>
In reply to#70303
On 12/6/2019 1:15 PM, Soviet_Mario wrote:
>>> sth like
>>>
>>> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
>>>
>>>
>>> template <RestrictedValues ttVal> class SizedField
>>
>> However, you're not using an enumerated type as a template argument,
>> you're using a enumeration value. 
> 
> Mmmm, exactly the point I am misunderstanding. I believed to have been 
> able to establish a proper type-checking in that declaration.
> How instead it should have been written ?
> can you correct my example in order to non accept non specific-enum 
> integral instancing ?

As other have pointed out, it appears that what you want is a template 
with a "non-type template parameter", the parameter being an enum value.

I did not check the standard, but it appears that this gives the type 
checking you are looking for.
following up on the sample from Paavo:

> What you wrote was basically correct syntax (after commenting out "etc etc"). This compiles fine:
> 
> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
> 
> template <RestrictedValues ttVal> class SizedField
> {
> private:
>     unsigned char zzArray[ttVal];
> 
> 
> public:
> 
>     //etc etc
> 
> };
> 
> int main() {
>     SizedField<B> foo;

   SizedField<42> bar;

> } 

This is what gcc reports:

$ c++ -std=c++17 -Wall templateArgEnum.cc
templateArgEnum.cc: In function ‘int main()’:
templateArgEnum.cc:22:16: error: invalid conversion from ‘int’ to 
‘RestrictedValues’ [-fpermissive]
    22 |   SizedField<42> bar;
       |                ^
       |                |
       |                int
templateArgEnum.cc:21:17: warning: unused variable ‘foo’ [-Wunused-variable]
    21 |   SizedField<B> foo;
       |                 ^~~
templateArgEnum.cc:22:18: warning: unused variable ‘bar’ [-Wunused-variable]
    22 |   SizedField<42> bar;
       |                  ^~~

[toc] | [prev] | [next] | [standalone]


#70314

FromSoviet_Mario <SovietMario@CCCP.MIR>
Date2019-12-06 18:43 +0100
Message-ID<qse40u$eth$1@dont-email.me>
In reply to#70297
Il 05/12/19 23:20, Soviet_Mario ha scritto:
> since what version of standard, if any, an ENUM type can be 
> an argument of a template ?
> 
> sth like
> 
> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
> 
> 
> template <RestrictedValues ttVal> class SizedField
> {
> private:
> unsigned char zzArray [ttVal];
> 
> 
> public:
> 
> etc etc
> 
> }
> 
> 
> or if the syntax is wrong, how to workaround ?
> 
> The goal is to have a template depending on a restricted 
> well defined, and known at compile time, set of integral values
> 
> 
> 
> 
> 
> 
> 
tnx for all for elucidations.
I still have some confused ideas about template instancing, 
but I don't know exactly what to ask. So I make more 
"experiments" before.
Ciao

-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)

[toc] | [prev] | [next] | [standalone]


#70329

Fromsaturnman2008@gmail.com
Date2019-12-07 01:53 -0800
Message-ID<4626047e-db85-4979-b2de-e36bd0955a02@googlegroups.com>
In reply to#70297
在 2019年12月6日星期五 UTC+8上午6:21:05,Soviet_Mario写道:
> since what version of standard, if any, an ENUM type can be 
> an argument of a template ?
> 
> sth like
> 
> enum class RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
> 
> 
> template <RestrictedValues ttVal> class SizedField
> {
  public:
 static constexpr int aSize = static_cast<int>(ttVal);
> private:

> unsigned char zzArray [aSize];
> 
> 
> public:
> 
> etc etc
> 
> }
> 
> 
> or if the syntax is wrong, how to workaround ?
> 
> The goal is to have a template depending on a restricted 
> well defined, and known at compile time, set of integral values
> 
> 
> 
> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };


template <RestrictedValues ttVal> class SizedField
{
private:
unsigned char zzArray [ttVal];


public:

etc etc

} 
> 
> 
> 
> -- 
> 1) Resistere, resistere, resistere.
> 2) Se tutti pagano le tasse, le tasse le pagano tutti
> Soviet_Mario - (aka Gatto_Vizzato)


If my modification fits your requirement?

[toc] | [prev] | [next] | [standalone]


#70340

FromSoviet_Mario <SovietMario@CCCP.MIR>
Date2019-12-07 18:57 +0100
Message-ID<qsgp75$lhp$1@dont-email.me>
In reply to#70329
Il 07/12/19 10:53, saturnman2008@gmail.com ha scritto:
> 在 2019年12月6日星期五 UTC+8上午6:21:05,Soviet_Mario写道:
>> since what version of standard, if any, an ENUM type can be
>> an argument of a template ?
>>
>> sth like
>>
>> enum class RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
>>
>>
>> template <RestrictedValues ttVal> class SizedField
>> {
>    public:
>   static constexpr int aSize = static_cast<int>(ttVal);
>> private:
> 
>> unsigned char zzArray [aSize];


Yes it was a slight of mine to not have converted an enum to 
int explicitely.
But the main question was not about that.
Anyway they have just reassured me that the compiler checks 
for invalid non-forced cast in the reverse sense (from a 
generic integer to the enum) in the specialization of an 
instance. That was the source of my concern.

The forced manual cast did not worry me, I try not to shoot 
in my foot :)

>>
>>
>> public:
>>
>> etc etc
>>
>> }
>>
>>
>> or if the syntax is wrong, how to workaround ?
>>
>> The goal is to have a template depending on a restricted
>> well defined, and known at compile time, set of integral values
>>
>>
>>
>> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
> 
> 
> template <RestrictedValues ttVal> class SizedField
> {
> private:
> unsigned char zzArray [ttVal];
> 
> 
> public:
> 
> etc etc
> 
> }
>>
>>
>>
>> -- 
>> 1) Resistere, resistere, resistere.
>> 2) Se tutti pagano le tasse, le tasse le pagano tutti
>> Soviet_Mario - (aka Gatto_Vizzato)
> 
> 
> If my modification fits your requirement?
> 


-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web