- What I'm doing wrong here? - 7 Updates
- Why do some people hate namespace prefixes? - 4 Updates
- static constexpr in a class - 8 Updates
- special string-implementation - 3 Updates
- [Jesus Loves You] Bible boring to you? Try this... - 1 Update
| "Heinz Müller" <Heinz.Mueller69@gmail.com>: Apr 22 05:09PM +0200 #include <type_traits> using namespace std; template<typename T> void f123( typename enable_if<is_unsigned<T>::value, T>::type t ) { } int main() { unsigned u; int i; f123( u ); f123( i ); // shoudn't work } Why dows the compiler not find at least the "valid" unsigned f123? |
| gazelle@shell.xmission.com (Kenny McCormack): Apr 22 03:13PM In article <q9klf7$gah$1@news.albasani.net>, > f123( i ); // shoudn't work >} >Why dows the compiler not find at least the "valid" unsigned f123? Your program has undefined behavior, so anything is possible. And, anything is right. And, so on... -- Religion is what keeps the poor from murdering the rich. - Napoleon Bonaparte - |
| Manfred <noname@invalid.add>: Apr 22 06:34PM +0200 On 4/22/19 5:09 PM, Heinz Müller wrote: > f123( i ); // shoudn't work > } > Why dows the compiler not find at least the "valid" unsigned f123? I'm not sure why, but typically enable_if is used either on template arguments or on return value types. It works if rewritten as follows: #include <type_traits> #include <iostream> using namespace std; template<typename T, typename = typename enable_if<is_unsigned<T>::value, T>::type> void f123( T t ) { cout << "f123(" << t << ")" << endl; } int main() { unsigned u = 1; int i = 2; f123( u ); f123( i ); // shoudn't work } (I added the required initializers to get rid of UB) |
| Manfred <noname@invalid.add>: Apr 22 06:40PM +0200 On 4/22/19 6:34 PM, Manfred wrote: > f123( i ); // shoudn't work > } > (I added the required initializers to get rid of UB) As said, also with return types: #include <type_traits> #include <iostream> using namespace std; template<typename T> typename enable_if<is_unsigned<T>::value, void>::type f123( T t ) { cout << "f123(" << t << ")" << endl; } int main() { unsigned u = 1; int i = 2; f123( u ); f123( i ); // shoudn't work } |
| "Heinz Müller" <Heinz.Mueller69@gmail.com>: Apr 22 07:12PM +0200 > { > cout << "f123(" << t << ")" << endl; > } That seems more intuitive. But what does the ", typename = ..." above mean? ---------- |
| Manfred <noname@add.invalid>: Apr 22 10:40PM +0200 On 4/22/2019 7:12 PM, Heinz Müller wrote: > That seems more intuitive. > But what does the ", typename = ..." above mean? > ---------- That is an unnamed template argument, with a default that is the result of enable_if. In the template it is a placeholder for a type argument that is not used - in fact it is used only to trigger the evaluation of its default type, which is the result of the enable_if expression. |
| "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 22 11:25PM +0200 On 22.04.2019 17:09, Heinz Müller wrote: > f123( i ); // shoudn't work > } > Why dows the compiler not find at least the "valid" unsigned f123? Template argument deduction doesn't work on *dependent* types, like the ...::type for your formal argument. From the compiler's point of view there could be any number of specializations of `enable_if`, with `::type`s that didn't at all resemble the `T` type. And these specialization could be defined in indirect ways that involved much compile time activity to straighten out. It would be unreasonable to require it to do that /in general/. Template argument deduction is instead a more or less direct matching, not considering any type indirection. So, to do what you're trying to do, do template< class T, class = enable_if_t< is_unsigned_v< T > > void f123( const T value ) ... Due to historical reasons, that template aliases were not available at the time the `enable_if` appeared, the notation is full of annoying ticks and warts like `_t` and `_v`. I tend to reduce them via ¹simple aliases, e.g., off the cuff template< bool condition > using Enable_if_ = std::enable_if_t<condition>; In some cases, such as `is_const_` and `is_base_and_derived_`, the wrapper or alias also adds much needed generality or clarity. Cheers! - Alf References: ¹ E.g. see <url: https://github.com/alf-p-steinbach/cppx-core/blob/master/source/cppx-core/language/tmp/basic-type-traits.hpp> |
| Chris Sykes <chris@amtiskaw.net>: Apr 22 10:32AM +0100 On 21/04/2019 14:09, Bart wrote: > the #include, it doesn't work (doesn't know 'std'); if I keep that > but get rid of std::, it doesn't work either (doesn't know 'cout'). > And this is the simplest possible program. Well in C++ you can always add: using std::cout, std::string; // comma separated list allowed since c++17 To pull in precisely what you want to use from the standard library, or: using std; To dump everything into the local scope. The biggest advantage (IMO) of C++ namespaces is that they provide a mechanism to resolve otherwise ambiguous names; that is, even when `using std;`, you can fully qualify references to string, cout or whatever to resolve any ambiguity with symbols defined elsewhere. Many other languages do something similar; the compiler (or interpreter) raises an error (hopefully identifying where the conflicting symbols are declared), and you fix it by qualifying the references with the appropriate namespace, package, module/whatever prefix. |
| Chris Sykes <chris@amtiskaw.net>: Apr 22 10:43AM +0100 On 21/04/2019 13:37, Juha Nieminen wrote: > undrestandability of code shouldn't be reliant on an IDE. The code > should remain readable and understandable even if you are just looking > at it with a vanilla text editor. Absolutely. Time saved in code review (or just coming back to some code *you* wrote a while ago) vastly outweighs a few characters saved when first entering the code, and both IDEs and editors tend to have pretty good auto-complete when entering code these days anyway. |
| Jorgen Grahn <grahn+nntp@snipabacken.se>: Apr 22 03:37PM On Thu, 2019-04-18, Fred.Zwarts wrote: >>locally, and don't expect such a name to conflict with the standard >>library. Not to mention names like find(). > I don't think it is wise to use such a widely used name as 'string' locally. I do. Namespaces were added to C++ (at least partly) to allow that; seems a waste not to take advantage of it. How much of an advantage it is varies from person to person. Personally I find prefixes quite distracting: I strongly prefer e.g. "insert(a, b)" to "my_insert(a, b)". /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
| Jorgen Grahn <grahn+nntp@snipabacken.se>: Apr 22 04:07PM >> people just hate namespace prefixes in C++, and go to great lengths >> to avoid them and will rabidly defend this practice, and oppose their >> use. No amoung of argumentation will convince them otherwise. ... > Earth::wind, Earth::rock > When I see 'wind', 'rock', how am I supposed to think with these words? > Mars_wind, Earth_rock would be more clearer. Just like Mars::wind and Earth::rock. IMHO you're missing part of the point of namespaces. You're supposed to /know/ when you're inside it, much like you're supposed to know what planet you're on. Or, if I had a brother called Donald, I'd call him "Donald" when talking to my sister. I wouldn't call him "Donald Grahn" to make it clear I'm not talking about Donald Duck, or Knuth. If I did, my sister would be confused and possibly worried. When you're not inside the namespace, using the full name is normally the way to go: if a whole class or function only works on Earth::rock, then that's a sign maybe it should have been in the Earth namespace. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
| blt_7W@zimftew_1xvn.com: Apr 22 08:31AM On Sun, 21 Apr 2019 13:34:25 +0200 >> const. >/I/ am the person writing these functions here. /I/ know they are not >simple arithmetic. The result of some of the functions is a single You must have a magic compiler that can execute loops, call other functions and execute other non arithmetic and boolean logic constructs at compile time then. >integer, others result in arrays of data, but the functions involved are >not simple. There are good reasons why I am using functions, not just Give us an example of these complex functions that can still be reduced to a single value at compile time. |
| David Brown <david.brown@hesbynett.no>: Apr 22 11:33AM +0200 >> simple arithmetic. The result of some of the functions is a single > You must have a magic compiler that can execute loops, call other functions and > execute other non arithmetic and boolean logic constructs at compile time then. It's a C++14 compiler - there are several available. C++14 removed many of the restrictions on C++11 constexpr functions. <https://en.cppreference.com/w/cpp/language/constexpr> >> not simple. There are good reasons why I am using functions, not just > Give us an example of these complex functions that can still be reduced to > a single value at compile time. The code below is originally from C, rather than C++, simply augmented by "constexpr". Even with optimisation disabled, a C++14 compiler must calculate the CRC check here at compile time. #include <stdint.h> #include <string.h> static constexpr const uint8_t crcTable8[256] = { 0x00, 0x8D, 0x97, 0x1A, 0xA3, 0x2E, 0x34, 0xB9, 0xCB, 0x46, 0x5C, 0xD1, 0x68, 0xE5, 0xFF, 0x72, 0x1B, 0x96, 0x8C, 0x01, 0xB8, 0x35, 0x2F, 0xA2, 0xD0, 0x5D, 0x47, 0xCA, 0x73, 0xFE, 0xE4, 0x69, 0x36, 0xBB, 0xA1, 0x2C, 0x95, 0x18, 0x02, 0x8F, 0xFD, 0x70, 0x6A, 0xE7, 0x5E, 0xD3, 0xC9, 0x44, 0x2D, 0xA0, 0xBA, 0x37, 0x8E, 0x03, 0x19, 0x94, 0xE6, 0x6B, 0x71, 0xFC, 0x45, 0xC8, 0xD2, 0x5F, 0x6C, 0xE1, 0xFB, 0x76, 0xCF, 0x42, 0x58, 0xD5, 0xA7, 0x2A, 0x30, 0xBD, 0x04, 0x89, 0x93, 0x1E, 0x77, 0xFA, 0xE0, 0x6D, 0xD4, 0x59, 0x43, 0xCE, 0xBC, 0x31, 0x2B, 0xA6, 0x1F, 0x92, 0x88, 0x05, 0x5A, 0xD7, 0xCD, 0x40, 0xF9, 0x74, 0x6E, 0xE3, 0x91, 0x1C, 0x06, 0x8B, 0x32, 0xBF, 0xA5, 0x28, 0x41, 0xCC, 0xD6, 0x5B, 0xE2, 0x6F, 0x75, 0xF8, 0x8A, 0x07, 0x1D, 0x90, 0x29, 0xA4, 0xBE, 0x33, 0xD8, 0x55, 0x4F, 0xC2, 0x7B, 0xF6, 0xEC, 0x61, 0x13, 0x9E, 0x84, 0x09, 0xB0, 0x3D, 0x27, 0xAA, 0xC3, 0x4E, 0x54, 0xD9, 0x60, 0xED, 0xF7, 0x7A, 0x08, 0x85, 0x9F, 0x12, 0xAB, 0x26, 0x3C, 0xB1, 0xEE, 0x63, 0x79, 0xF4, 0x4D, 0xC0, 0xDA, 0x57, 0x25, 0xA8, 0xB2, 0x3F, 0x86, 0x0B, 0x11, 0x9C, 0xF5, 0x78, 0x62, 0xEF, 0x56, 0xDB, 0xC1, 0x4C, 0x3E, 0xB3, 0xA9, 0x24, 0x9D, 0x10, 0x0A, 0x87, 0xB4, 0x39, 0x23, 0xAE, 0x17, 0x9A, 0x80, 0x0D, 0x7F, 0xF2, 0xE8, 0x65, 0xDC, 0x51, 0x4B, 0xC6, 0xAF, 0x22, 0x38, 0xB5, 0x0C, 0x81, 0x9B, 0x16, 0x64, 0xE9, 0xF3, 0x7E, 0xC7, 0x4A, 0x50, 0xDD, 0x82, 0x0F, 0x15, 0x98, 0x21, 0xAC, 0xB6, 0x3B, 0x49, 0xC4, 0xDE, 0x53, 0xEA, 0x67, 0x7D, 0xF0, 0x99, 0x14, 0x0E, 0x83, 0x3A, 0xB7, 0xAD, 0x20, 0x52, 0xDF, 0xC5, 0x48, 0xF1, 0x7C, 0x66, 0xEB }; static constexpr uint8_t crcData8(uint8_t crc, const uint8_t* pData, size_t size) { while (size--) { crc = crcTable8[crc ^ (*pData++)]; } return crc; } uint8_t test(void) { const uint8_t s[] = "Hello, world!"; constexpr uint8_t c = crcData8(0, s, sizeof(s)); return c; } |
| blt_q7_a8fplu@0gkdzjla5uk04q8c.com: Apr 22 09:53AM On Mon, 22 Apr 2019 11:33:48 +0200 >The code below is originally from C, rather than C++, simply augmented >by "constexpr". Even with optimisation disabled, a C++14 compiler must >calculate the CRC check here at compile time. Or not even in 2017 mode.... fenris$ c++ -v Apple LLVM version 10.0.1 (clang-1001.0.46.4) Target: x86_64-apple-darwin18.5.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin fenris$ c++ -std=c++17 test.cc test.cc:49:24: error: constexpr variable 'c' must be initialized by a constant expression constexpr uint8_t c = crcData8(0, s, sizeof(s)); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ test.cc:42:40: note: read of non-constexpr variable 's' is not allowed in a constant expression crc = crcTable8[crc ^ (*pData++)]; ^ test.cc:49:28: note: in call to 'crcData8(0, &s[1], 13)' constexpr uint8_t c = crcData8(0, s, sizeof(s)); ^ 1 error generated. Whoops. |
| Ian Collins <ian-news@hotmail.com>: Apr 22 10:05PM +1200 >> by "constexpr". Even with optimisation disabled, a C++14 compiler must >> calculate the CRC check here at compile time. > Or not even in 2017 mode.... It is if you fix the spello: constexpr uint8_t s[] = "Hello, world!"; gcc is a bit lenient on the original. -- Ian. |
| David Brown <david.brown@hesbynett.no>: Apr 22 12:14PM +0200 On 22/04/2019 12:05, Ian Collins wrote: > It is if you fix the spello: > constexpr uint8_t s[] = "Hello, world!"; > gcc is a bit lenient on the original. So it is - even in pedantic mode. I guess that could be filed as a bug. (clang will, of course, do everything at compile time with "s" being "const", as long as "c" is also changed to "const" instead of "constexpr". But it then does so for optimisation, not because the rules of C++ require it.) |
| blt_zwrtvhou@mlz0jr60in9.ac.uk: Apr 22 02:42PM On Mon, 22 Apr 2019 22:05:32 +1200 >> Or not even in 2017 mode.... >It is if you fix the spello: > constexpr uint8_t s[] = "Hello, world!"; Hmm, thats interesting. Guess I should have caught up with 2014 constexprs. I can't help thinking that the compiler executing code at compile time could be an interesting avenue for obscure bugs and compile time crashes. |
| David Brown <david.brown@hesbynett.no>: Apr 22 05:05PM +0200 > Hmm, thats interesting. Guess I should have caught up with 2014 constexprs. > I can't help thinking that the compiler executing code at compile time could > be an interesting avenue for obscure bugs and compile time crashes. Obscure bugs, yes. Compile time crashes are just compile-time error messages. There are still restrictions on what you can do in constexpr functions, of course. But they are a lot less than in C++11. |
| blt_2D6@zz6h0uww529.com: Apr 22 03:26PM On Mon, 22 Apr 2019 17:05:27 +0200 >> be an interesting avenue for obscure bugs and compile time crashes. >Obscure bugs, yes. Compile time crashes are just compile-time error >messages. No I was thinking of an actual compiler crash if its get stuck trying to solve some version of the halting problem and blows up. A compiler is just a program after all and a very complex one to boot so hidden bugs are almost a certainty. A good one in the past was feeding this to some old versions of the Solaris compiler: class myabstractclass { : virtual void func() = 1; : }; Caused a fairly comprehensive compiler internal error dump. |
| Thiago Adams <thiago.adams@gmail.com>: Apr 22 05:08AM -0700 On Friday, April 19, 2019 at 11:40:57 AM UTC-3, Bonita Montero wrote: > could increase the performance of string-handling significantly. On the > other side, there are many standard-library facilities that only accept > a basic_string so this type of string would be incompatible. In C, I use my own version called "LocalStringBuilder" http://thradams.com/localstrbuilder.htm It uses a buffer in the stack but if necessary it allocates memory on heap. In C++ (maybe?) this can be done changing the allocator of std::string or creating a new specialized template class. |
| James Kuyper <jameskuyper@alumni.caltech.edu>: Apr 22 09:02AM -0400 On 4/20/19 4:32 PM, Melzzzzz wrote: >> "stacticized" strings like in C this wouldn't blow up the stack to its >> maximum size. > Arrays on stack is always bad idea. Can you give a reason for that judgment that isn't addressed by choosing a large stack size and allocating only small arrays on the stack (for suitable values of "large" and "small")? |
| "Öö Tiib" <ootiib@hot.ee>: Apr 22 07:22AM -0700 On Friday, 19 April 2019 17:40:57 UTC+3, Bonita Montero wrote: > could increase the performance of string-handling significantly. On the > other side, there are many standard-library facilities that only accept > a basic_string so this type of string would be incompatible. Sure there are such classes. Fair amount of optimizations can be done by using std::array or mundane array plus std::string_view. That combo fits fully to stack. Alternatively (for fans of compile-time processing) that combo can be fully constexpr. When there is issue that even the length of string (and its buffer needed) is uncertain compile-time then unfortunately there are no standard solutions since neither VLA nor alloca() are in C++ (but one and/or other is usually supported as extension). However first I always make unoptimized version (that just uses std::strings) fully ready and covered with tests. Budget for performance works is lot easier to get when there is something that is worth to optimize. Otherwise such tinkering wastes too lot of time first and makes C++ team to look sluggish compared to Python or Java team. |
| "Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 21 06:49PM -0700 On Friday, April 19, 2019 at 4:05:13 PM UTC-4, Mr Flibble wrote: > And Satan invented fossils, yes? You are citing arguments I've never made as though they were my arguments, and using it to refute something that it not something I believe or have ever taught. If you want to know the truth ... learn it: https://groups.google.com/d/msg/comp.lang.c/YLNsjdKKFR4/VapszCkrCwAJ -- Rick C. Hodgin |
| 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