Tuesday, August 23, 2016

Digest for comp.lang.c++@googlegroups.com - 25 updates in 5 topics

ram@zedat.fu-berlin.de (Stefan Ram): Aug 23 04:49PM

>const int A::table[] = {0, 1, 2, 3, 4};
 
In this case, »table[ 0 ]« can be replace by »0«.
In this case, »table[ 1 ]« can be replace by »1«.
In this case, »table[ 2 ]« can be replace by »2«.
In this case, »table[ 3 ]« can be replace by »3«.
In this case, »table[ 4 ]« can be replace by »4«.
ram@zedat.fu-berlin.de (Stefan Ram): Aug 23 04:51PM

>const int A::table[] = {0, 1, 2, 3, 4};
 
#include <iostream>
#include <ostream>
 
#define TABLE0 0
#define TABLE1 1
#define TABLE2 2
#define TABLE3 3
#define TABLE4 4
#define TABLE(x) TABLE##x
 
int main()
{ ::std::cout << TABLE( 0 )<< '\n';
::std::cout << TABLE( 1 )<< '\n';
::std::cout << TABLE( 2 )<< '\n';
::std::cout << TABLE( 3 )<< '\n';
::std::cout << TABLE( 4 )<< '\n'; }
ram@zedat.fu-berlin.de (Stefan Ram): Aug 23 05:15PM

>int y = x -'0';
>Is this the C++ 11 way of doing this or is there a better way? Should I
>put x into a string of length 1 and use atoi?
 
If you only ever have the value of »'8'« you can write
 
int y = 8;
 
. If you also have /other/ character values it depends on what you
want them to be converted /into/.
 
I think, one could give the intended mapping rule /in English/ and
then we could figure out how to implement this rule in C++.
ram@zedat.fu-berlin.de (Stefan Ram): Aug 23 07:56PM

>Maybe that isnt't clear from the post, but it's supposed to be a lookup
>table and also needs to work for dynamic lookups.
 
#include <iostream>
#include <ostream>
 
#define F(i) i,
#define TABLE \
F( 0 )\
F( 1 )\
F( 2 )\
F( 3 )\
F( 4 )
int array[] ={ TABLE };
#undef F
 
#define F(i) TABLE##i=i,
enum table { TABLE };
#undef F
 
int main( void )
{ switch( 0 ){ case TABLE0: int i = 0; ::std::cout << array[ 0 ]<< '\n'; }}
ram@zedat.fu-berlin.de (Stefan Ram): Aug 23 08:00PM

>F( 2 )\
>F( 3 )\
>F( 4 )
 
A superficial change: This, of course, can be written
more compact as
 
#define TABLE F(0)F(1)F(2)F(3)F(4)
 
.
ram@zedat.fu-berlin.de (Stefan Ram): Aug 23 08:20PM

>#define F(i) TABLE##i=i,
 
This would work only in the special case given.
 
Here is a new, more general version:
 
#include <iostream>
#include <ostream>
 
#define F(i,j) (j),
#define TAB F(0,0)F(1,1)F(2,2)F(3,3)F(4,4)
int array[] ={ TAB };
#undef F
 
#define F(i,j) TAB##i=(j),
enum table { TAB };
#undef F
 
#define TABLE(i) TAB##i
 
int main( void )
{ int i; switch( 0 ){ case TABLE( 0 ): case TABLE( 1 ): case TABLE( 2 ): ; }
::std::cout << TABLE( 0 )<< '\n'; i = 0; ::std::cout << array[ i ]<< '\n';
::std::cout << TABLE( 1 )<< '\n'; i = 1; ::std::cout << array[ i ]<< '\n';
::std::cout << TABLE( 2 )<< '\n'; i = 2; ::std::cout << array[ i ]<< '\n'; }
 
The programmer must choose himself to use »TABLE« for compile-time lookup
and »array« for run-time lookup for each lookup case.
ram@zedat.fu-berlin.de (Stefan Ram): Aug 23 09:29PM

>The programmer must choose himself to use »TABLE« for compile-time lookup
>and »array« for run-time lookup for each lookup case.
 
The next program is a really ugly hack, where the programmer can write
»TABLE( 0 )« for a compile-time value and »TABLE( i )« for a run-time
value. But this is no general solution, it only works for the variable
name »i«, which must be an int variable, and integer literals.
 
#include <iostream>
#include <ostream>
 
#define F(i,j) (j),
#define TAB F(0,0)F(1,1)F(2,2)F(3,3)F(4,4)
int array[] ={ TAB };
#undef F
 
#define F(i,j) TAB##i=(j),
enum table { TAB };
#undef F
 
#define TABLE(i) TAB##i
#define TABi ((array)[(i)])
 
int main( void )
{ int i; switch( 0 ){ case TABLE( 0 ): case TABLE( 1 ): case TABLE( 2 ): ; }
::std::cout << TABLE( 0 )<< '\n'; i = 0; ::std::cout << TABLE( i )<< '\n';
::std::cout << TABLE( 1 )<< '\n'; i = 1; ::std::cout << TABLE( i )<< '\n';
::std::cout << TABLE( 2 )<< '\n'; i = 2; ::std::cout << TABLE( i )<< '\n'; }
mark <mark@invalid.invalid>: Aug 23 05:53PM +0200

What is a good way to use a lookup table at compile time? Using C++11 is
not an option (must work with GCC 4.3). This is for embedded usage with
tiny amounts of memory and every byte counts. Having increased code or
data size compared to hardcoding things is not an option.
 
E.g:
 
---------------------------------------------------
class A {
public:
void m();
private:
static const int table[5];
};
 
void A::m() {
int arr[table[3]]; // table[3] is not compile time const
}
 
const int A::table[] = {0, 1, 2, 3, 4};
---------------------------------------------------
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Aug 23 12:08PM -0700

On Tuesday, August 23, 2016 at 11:54:01 AM UTC-4, mark wrote:
> }
 
> const int A::table[] = {0, 1, 2, 3, 4};
> ---------------------------------------------------
 
I was surprised nobody's replied by now. I'm not sure what the best
way to do it in C++ is, but if you know explicitly these constants at
compile-time, such that you're referencing table[3], then you could
use an enum like this:
 
class A {
public:
void m();
 
private:
enum { first = 0, one, two, three, four };
};
 
void A::m() {
int arr[A::three]; // A::three is a compile time const
}
 
-----
You could also define compile-time constants for the values 0, 1, 2,
3, and 4, and define constants which reference those constants using
a similar name, like...:
 
#define _const0 0
#define _const1 1
#define _const2 2
#define _const3 3
#define _const4 4
 
const int A::table[] = {_const0, _const1, _const2, _const3, _const4};
 
#define table0 _const0
#define table1 _const1
#define table2 _const2
#define table3 _const3
#define table4 _const4
 
...so that instead of using "table[3]" you'd use "table3" which would map
to the same constant value:
 
int arr[table3]; // Make sure table3's declared ahead of use
 
These are the solutions I would use if I had constraints. I am, however,
curious what the proper C++ solution is.
 
Best regards,
Rick C. Hodgin
mark <mark@invalid.invalid>: Aug 23 09:26PM +0200

On 2016-08-23 18:51, Stefan Ram wrote:
> ::std::cout << TABLE( 2 )<< '\n';
> ::std::cout << TABLE( 3 )<< '\n';
> ::std::cout << TABLE( 4 )<< '\n'; }
 
Maybe that isnt't clear from the post, but it's supposed to be a lookup
table and also needs to work for dynamic lookups.
 
I.e.:
 
void A::m2(int i) {
return table[i] * 42;
}
 
needs to work.
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Aug 23 12:36PM -0700

On Tuesday, August 23, 2016 at 3:27:04 PM UTC-4, mark wrote:
> return table[i] * 42;
> }
 
> needs to work.
 
The second solution I provided would allow your option here to work.
It simply migrates the constant values from being specified in the
{ ... } definition into #define tokens, but it still creates table.
 
#define _const0 0
#define _const1 1
#define _const2 2
#define _const3 3
#define _const4 4
 
const int A::table[] = {_const0, _const1, _const2, _const3, _const4};
 
#define table0 _const0
#define table1 _const1
#define table2 _const2
#define table3 _const3
#define table4 _const4
 
void A::m() {
int arr[table3];
}
 
void A::m2(int i) {
return table[i] * 42;
}
 
Both would be valid.
 
Best regards,
Rick C. Hodgin
mark <mark@invalid.invalid>: Aug 23 09:44PM +0200

On 2016-08-23 21:08, Rick C. Hodgin wrote:
 
> int arr[table3]; // Make sure table3's declared ahead of use
 
> These are the solutions I would use if I had constraints. I am, however,
> curious what the proper C++ solution is.
 
Thank's. I was hoping for something more elegant.
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Aug 23 12:49PM -0700

On Tuesday, August 23, 2016 at 3:44:21 PM UTC-4, mark wrote:
 
> > These are the solutions I would use if I had constraints. I am, however,
> > curious what the proper C++ solution is.
 
> Thank's. I was hoping for something more elegant.
 
Well, I'm sure someone else will be able to provide you with a more
elegant solution. I apologize if my offering offended you.
 
Best regards,
Rick C. Hodgin
legalize+jeeves@mail.xmission.com (Richard): Aug 23 08:00PM

[Please do not mail me a copy of your followup]
 
First, let me say that you've posed a very specific question with a
generic example in the form of "how do I perform this task?" but you
haven't told us the actual goal the task is supposed to accomplish.
 
Eric Raymond calls this "describe the goal, not the step". Here
you've described the step and not the goal. If we knew the goal, we
could probably advise you more fully on the best way to achieve it.
<http://www.catb.org/esr/faqs/smart-questions.html#goal>
 
Let's proceed...
 
mark <mark@invalid.invalid> spake the secret code
 
>What is a good way to use a lookup table at compile time?
 
An easier solution might be to simply generate source files at build
time that reflect whatever it is you're trying to do at compile time.
 
Compile-time evaluation occurs through one of two C++ mechanisms:
templates and constexpr. Since you are using an ancient gcc, you
can't use constexpr. That leaves templates. (I'm ignoring
preprocessor hacks, I'm sure someone else will post a disgusting
solution using macros.)
 
Templates can implement a table-lookup type mechanism through
a generic template and one specialization of the generic template for
each input to the lookup. The outputs are obtained through the
differences in the specializations.
 
> int arr[table[3]]; // table[3] is not compile time const
>}
 
>const int A::table[] = {0, 1, 2, 3, 4};
 
template <int Index>
struct table
{
static const int value;
};
 
template <>
struct table<0>
{
static const int value = 0;
};
 
template <>
struct table<1>
{
static const int value = 1;
};
 
template <>
struct table<2>
{
static const int value = 2;
};
 
template <>
struct table<3>
{
static const int value = 3;
};
 
template <>
struct table<4>
{
static const int value = 4;
};
 
class A
{
public:
void m();
};
 
void A::m()
{
int arr[table<3>::value];
for (int i = 0; i < sizeof(arr)/sizeof(int); ++i)
{
arr[i] = 2*i;
}
}
 
int main()
{
A a;
a.m();
}
 
So yeah, that works, but it's pretty noisy.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
mark <mark@invalid.invalid>: Aug 23 11:06PM +0200

On 2016-08-23 21:49, Rick C. Hodgin wrote:
>> > Thank's. I was hoping for something more elegant.
> Well, I'm sure someone else will be able to provide you with a more
> elegant solution. I apologize if my offering offended you.
 
This wasn't intended to be ironic or anything. Your second suggestion
may very well be what I will use.
 
Which doesn't mean I'm happy with it, what I really want is something like:
 
class A {
public:
void m();
int m2(int v);
int m3(int v);
private:
static constexpr int table[5] = { 4, 1, 7, 2, 1 };
static constexpr int i = table[2];
};
 
void A::m() {
int arr[table[3]];
}
 
int A::m2(int v) {
return table[v] * 42;
}
 
int A::m3(int v) {
switch(v) {
case table[2]:
return 42;
default:
return -1;
}
}
mark <mark@invalid.invalid>: Aug 23 11:25PM +0200

On 2016-08-23 22:20, Stefan Ram wrote:
> ::std::cout << TABLE( 2 )<< '\n'; i = 2; ::std::cout << array[ i ]<< '\n'; }
 
> The programmer must choose himself to use »TABLE« for compile-time lookup
> and »array« for run-time lookup for each lookup case.
 
Wow, some neat macro (ab)use. I'm not sure other people will be
thrilled, if I use something like that.
Dombo <dombo@disposable.invalid>: Aug 23 10:11PM +0200

Op 21-Aug-16 om 11:19 schreef jacob navia:
 
>> Isn't it just a description of anyone else's code? :-)
 
> If after 15+ years the code is like that, imagine after just a few
> MILLION years...
 
After a few million years some of the people looking at the code will
conclude there must be an intelligent design behind it and that the
first lines of code were conceived about 6000 years before ;-)
Joseph Hesse <joeh@gmail.com>: Aug 23 12:05PM -0500

I have a char x = '8' and want to use this to put the integer 8 into an
int variable. I know I can do it this way:
 
char x = '8';
int y = x -'0';
 
Is this the C++ 11 way of doing this or is there a better way? Should I
put x into a string of length 1 and use atoi?
 
Thank you,
Joe
Victor Bazarov <v.bazarov@comcast.invalid>: Aug 23 01:23PM -0400

On 8/23/2016 1:05 PM, Joseph Hesse wrote:
> int y = x -'0';
 
> Is this the C++ 11 way of doing this or is there a better way? Should I
> put x into a string of length 1 and use atoi?
 
There is no need for atoi. The C++ character set works the way you
showed for all decimal digits.
 
V
--
I do not respond to top-posted replies, please don't ask
scott@slp53.sl.home (Scott Lurndal): Aug 23 07:28PM

>> put x into a string of length 1 and use atoi?
 
>There is no need for atoi. The C++ character set works the way you
>showed for all decimal digits.
 
C++ character set?
 
In reality, whether the underlying encoding is ASCII, EBCDIC or UTF-8,
the technique of subtracting the character '0' from any other numeric
character value will work properly.
Victor Bazarov <v.bazarov@comcast.invalid>: Aug 23 03:38PM -0400

On 8/23/2016 3:28 PM, Scott Lurndal wrote:
>> showed for all decimal digits.
 
> C++ character set?
> [.. blahblah ..]
 
Yes, please see the Standard, [lex.charset]. The first paragraph starts
with "The /basic character set/ consists".
 
V
--
I do not respond to top-posted replies, please don't ask
David Brown <david.brown@hesbynett.no>: Aug 23 08:59AM +0200

On 23/08/16 00:57, Öö Tiib wrote:
> worldwide". Why google is better than others? Amazon pays taxes, oracle
> pays taxes, microsoft pays taxes, apple pays taxes. Google should pay
> taxes too.
 
I agree that Google should pay taxes - but none of these other companies
pays taxes in the way small companies or individuals do. They /all/
have armies of lawyers and accountants whose job is to minimise the
taxes paid, to make sure profits are shuffled around from company to
company and country to country until tax authorities have lost track.
/None/ of them pay an appropriate level of tax in the countries where
they make they money. So while I fully agree that Google is bad at
this, it is no worse than the other big IT companies.
 
 
> They indeed have a odd religion against C++ exceptions. So if other
> frameworks did not compile with exceptions turned off then they had
> to make their own.
 
Google are not alone in disliking C++ exceptions - it is a better
attitude than many C++ programmers who write code that occasionally uses
exceptions, but don't really understand all the details needed to make
properly exception-safe code, or who treat exceptions as just a way of
giving the user an error message when something goes wrong.
Lynn McGuire <lynnmcguire5@gmail.com>: Aug 22 12:49PM -0500

On 8/20/2016 5:20 PM, Lynn McGuire wrote:
> http://stackoverflow.com/questions/1287425/automated-testing-for-c-c-gui-applications
 
> Thanks,
> Lynn
 
Interesting article, "Why Are There So Many C++ Testing Frameworks?":
http://googletesting.blogspot.com/2012/10/why-are-there-so-many-c-testing.html
 
Lynn
legalize+jeeves@mail.xmission.com (Richard): Aug 22 07:54PM

[Please do not mail me a copy of your followup]
 
Lynn McGuire <lynnmcguire5@gmail.com> spake the secret code
 
>Interesting article, "Why Are There So Many C++ Testing Frameworks?":
 
>http://googletesting.blogspot.com/2012/10/why-are-there-so-many-c-testing.html
 
Without reading the article, my guesses are:
 
- there wasn't one, so we made our own and kept using it
- open source egoism[*]
- there's no defacto standard like jUnit
- framework PQR doesn't do enough, so I made my own
- framework PQR does too much, so I made my own
 
Now let's go look at the article and see how I did.
 
Google says PQR doesn't do enough, so they made their own:
 
"The short answer is that we couldn't find an existing C++
testing framework that satisfied all our needs."
 
Which frankly I find hard to believe because there isn't anything in
GTest that wasn't already in Boost.Test AFAICT. Maybe it was the use
of exceptions they didn't like, I can't recall if Boost.Test relies
on exceptions or simply supports testing code that uses them.
 
[*] "open source egoism" is what I call the phenomenon of what
motivates people to contribute to open source. It's much sexier to
create your own thing from scratch than it is to do bug fixes on an
existing thing or enhance/extend an existing thing. Therefore, open
source software development tends to result in lots of greenfield
projects that do just enough to scratch the author's itch and they
don't build a community that extends them further. Therefore a
profusion of small greenfield projects appear, but none of them is
sufficiently embraced to gain dominance.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
Lynn McGuire <lynnmcguire5@gmail.com>: Aug 22 03:36PM -0500

On 8/22/2016 2:54 PM, Richard wrote:
> don't build a community that extends them further. Therefore a
> profusion of small greenfield projects appear, but none of them is
> sufficiently embraced to gain dominance.
 
And they are Google.
 
Lynn
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: