- Use of decltype - 6 Updates
- generic memoization of pure functions? - 1 Update
- Unsigned fixed point multiply refresher - 3 Updates
Paul <pepstein5@gmail.com>: Mar 11 03:56AM -0800 Suppose I want to sort a vector in reverse order, using std::greater. I use decltype because I don't want to explicitly state the type but I want to select the type of the first element. The code snippet is below: std::vector<int> v{1}; std::sort(v.begin(), v.end(), std::greater<decltype(v[0])>()); Why does this fail to compile? If v[0] is replaced by 5, it does compile. My thinking is that decltype(v[0]) means same type as v[0] which means same type as 1 which is int and that therefore std::sort(v.begin(),v.end(), std::greater<int>()); should be executed. Where am I going wrong? What should be done in practice if the type of v[0] is not simply int but a very complex type, and I want to avoid repeating the name of the type? I suppose typedef is the solution, but I thought decltype was used to solve this type of problem, too. Many thanks for your help. Paul |
Victor Bazarov <v.bazarov@comcast.invalid>: Mar 11 07:37AM -0500 On 3/11/2016 6:56 AM, Paul wrote: > Why does this fail to compile? If v[0] is replaced by 5, it does compile. My thinking is that decltype(v[0]) means same type as v[0] which means same type as 1 which is int and that therefore std::sort(v.begin(),v.end(), std::greater<int>()); should be executed. > Where am I going wrong? What should be done in practice if the type of v[0] is not simply int but a very complex type, and I want to avoid repeating the name of the type? I suppose typedef is the solution, but I thought decltype was used to solve this type of problem, too. > Many thanks for your help. It's possible that v[0] gives you not 'int', but 'int&', I'm too lazy to check now. If you wanted to use 'v' and 'decltype' to supply 'int' to instantiate 'greater', you could try ... std::greater<decltype(v)::value_type> ... V -- I do not respond to top-posted replies, please don't ask |
Paul <pepstein5@gmail.com>: Mar 11 05:18AM -0800 On Friday, March 11, 2016 at 12:37:49 PM UTC, Victor Bazarov wrote: > check now. If you wanted to use 'v' and 'decltype' to supply 'int' to > instantiate 'greater', you could try > ... std::greater<decltype(v)::value_type> ... Yes, this works. Thanks. Paul |
Juha Nieminen <nospam@thanks.invalid>: Mar 11 07:31PM > std::vector<int> v{1}; > std::sort(v.begin(), v.end(), std::greater<decltype(v[0])>()); I haven't tried, but this probably works: std::greater<std::remove_reference_t<decltype(v[0])>> Of course this is becoming needlessly verbose. Just use the vector's value_type. --- news://freenews.netfront.net/ - complaints: news@netfront.net --- |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 11 11:00PM +0100 On 11.03.2016 12:56, Paul wrote: > std::vector<int> v{1}; std::sort(v.begin(), v.end(), > std::greater<decltype(v[0])>()); > Why does this fail to compile? Sounds like a reference to me. Why not try decltype( +v[0] ) Disclaimer: I have not checked that. Also there was something about double parenthesis. They crammed too much into one thing, old g++ typeof was more practical. Cheers!, - Alf |
woodbrian77@gmail.com: Mar 11 03:09PM -0800 On Friday, March 11, 2016 at 4:01:17 PM UTC-6, Alf P. Steinbach wrote: > Sounds like a reference to me. > Why not try > decltype( +v[0] ) I think Victor's solution is clearer. The syntax you suggest reminds me of Perl - cryptic. Brian Ebenezer Enterprises - If you can't join 'em, beat 'em. http://webEbenezer.net |
bitrex <bitrex@de.lete.earthlink.net>: Mar 11 11:49AM -0500 On 03/06/2016 09:25 AM, Alf P. Steinbach wrote: > which gives O(f) ~= 2^n, which is rather ungood. Compared to O(n) for > iterative, or (but lacking the precision implied by bignum ints) O(1) > for using the golden ratio formula to compute the numbers directly. The recursive Fibonacci algorithm's big O behavior is essentially due to its shameless breaking of the first rule of algorithm design: never do the same work twice. |
bitrex <bitrex@de.lete.earthlink.net>: Mar 10 07:53PM -0500 Forgive me, my code-fu is a little rusty. The ARM Cortex M4 (Teensy audio library) I'm writing some C++ code for (for a personal project, I'm definitely not like, a professional) has a simple fixed point math library the author put together. I can't seem to find any references in the API to fixed point _unsigned_ multiply, however. I have an unsigned 16 bit fractional part number (Q15?) in a uint16_t, and I need to multiply another uint16_t with no fractional part by this to scale it. Apparently what I have available is a routine that multiples an int32_t by an int16_t and stuffs the result in an int32_t. IIRC I should be able to just treat the uint16_t as an int16_t and with twos complement it should work out OK, right? What would be the appropriate way to achieve what I need with what I have? |
David Brown <david.brown@hesbynett.no>: Mar 11 09:25AM +0100 On 11/03/16 01:53, bitrex wrote: > by an int16_t and stuffs the result in an int32_t. IIRC I should be able > to just treat the uint16_t as an int16_t and with twos complement it > should work out OK, right? In practice that will probably work, but in theory it will not. In C, signed and unsigned types have different overflow characteristics. It is possible that you will hit undefined behaviour due to overflows for some values. The compiler will probably generate code that will work as expected anyway (since the cpu uses two's complement even though C does not), but you should try to avoid the risk - weird things can happen if the compiler uses inlining and constant propagation to pre-calculate results. > What would be the appropriate way to achieve what I need with what I have? First, make sure you cast your operands to "unsigned int" before doing the multiplication. That makes sure everything stays unsigned, there are no overflows, and no risks of undefined behaviour. It is the compiler's job to spot that it can do everything using using 16-bit arithmetic instructions - your job is to make sure the C code is correct. Secondly, you probably want saturation on overflow, rather than simply taking the lowest 16 bits. If you multiply 0.25 (0x4000) by 5 (0x0005) you want the result to be 0.999984741 (0xffff), not 0.25 (after truncating 0x14000 to 0x4000). uint16_t multQ_U(uint16_t q, uint16_t u) { uint32_t x = (uint32_t) u * (uint32_t) q; if (x <= 0xffff) return (uint16_t) x; return 0xffff; } (That's for a UQ16, unsigned 16-bit format. If you have a 15-bit unsigned format, the saturation will be at 0x7fff.) An alternative option is to use <stdfix.h> and types such as "unsigned fract". This lets the compiler do the work of getting the code correct, but the resulting code can often be sub-optimal. In my quick tests, ARM gcc 4.8 did a good job of some things like multiplying two "fract" types, but quickly resorts to library calls for many other combinations. It is also not supported in C++. |
bitrex <bitrex@de.lete.earthlink.net>: Mar 11 08:40AM -0500 On 03/11/2016 03:25 AM, David Brown wrote: > gcc 4.8 did a good job of some things like multiplying two "fract" > types, but quickly resorts to library calls for many other combinations. > It is also not supported in C++. Thanks so much! This is an enormous help. |
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:
Post a Comment