- Nasty gotcha in template code generation - 5 Updates
- Adding a function to std::exception and company - 5 Updates
- Onwards and upwards - 2 Updates
- Tricky bug - 1 Update
Vir Campestris <vir.campestris@invalid.invalid>: Dec 18 11:13AM So I have a header file with some templated code in it. This is a simplified version template <typename T> void func() { std::cout << "in " << __PRETTY_FUNCTION__ << std::endl; method(T()); std::cout << "leaving " << __PRETTY_FUNCTION__ << std::endl; } You'll notice it calls "method". I also have a couple of cpp files, which use the template #include <iostream> template <typename T> void method(const T & param) { std::cout << "In method a " << __PRETTY_FUNCTION__ << std::endl; } #include "template.h" void a() { func<int>(); } they're identical, except in the second one the function at the bottom is called b, and the message in method says "In method b". From another file I call a and b. The messages indicate that BOTH calls to a and b call the same method() function. This is because the instantiated template function from both a.cpp and b.cpp have the same signature, so the linker throws one of them away. It took me a while to track it down in the real code. Andy |
Richard Damon <Richard@Damon-Family.org>: Dec 18 08:05AM -0500 On 12/18/20 6:13 AM, Vir Campestris wrote: > b.cpp have the same signature, so the linker throws one of them away. > It took me a while to track it down in the real code. > Andy Doesn't seem that surprising to me. You named two different functions with the same name so you should expect an issue. Now, being templates, the system is more apt to not detect the problem and report the issue. There is a similar issue with just plain global variables, which gcc just recently changed the behavior from ignoring to reporting and a lot of people are being caught unawares that it was a problem. |
"Öö Tiib" <ootiib@hot.ee>: Dec 18 08:52AM -0800 On Friday, 18 December 2020 at 13:13:36 UTC+2, Vir Campestris wrote: > This is because the instantiated template function from both a.cpp and > b.cpp have the same signature, so the linker throws one of them away. > It took me a while to track it down in the real code. Yes some violations of ODR are required to be detected by standard but others are that your program is ill formed but no diagnostic is required. Both the patterns "undefined behavior" and "no diagnostic is required" are massively represented in C++ standard so it will take years to learn to avoid those in your own code and even more years to notice in code of others. But committee releases more every 3 years so the process of learning C++ should be continuous. |
Vir Campestris <vir.campestris@invalid.invalid>: Dec 18 09:43PM On 18/12/2020 13:05, Richard Damon wrote: > Doesn't seem that surprising to me. You named two different functions > with the same name so you should expect an issue. Now, being templates, > the system is more apt to not detect the problem and report the issue. If I named two different ordinary functions the same I'd expect the linker to object. With template instantiations it optimises one away - based purely on the signature, not the content. I suppose it would be too hard to check the content. > There is a similar issue with just plain global variables, which gcc > just recently changed the behavior from ignoring to reporting and a lot > of people are being caught unawares that it was a problem. I don't think I follow you. Andy |
Richard Damon <Richard@Damon-Family.org>: Dec 18 06:18PM -0500 On 12/18/20 4:43 PM, Vir Campestris wrote: >> of people are being caught unawares that it was a problem. > I don't think I follow you. > Andy GCC has long allowed multiple translation units to define variables by the same name as globals (and not require that all but one be declared as extern to make them just declarations and not definitions). It did not check that they ware of the same type, but just put all of them at the same memory location. Defining globals by the same name in different translation units is undefined behavior (whether a function of a variable), but does not require a diagnostic. GCC has had an option that would flag this case as an error, but the default has been until a very recent version, to allow this to happen (for variables) by default. The recent version has changed the default to generate an error, and some programming communities are having fits due to this, as long working programs are now not building. The function issue brought up is very much of the same sort of thing. Normal functions will generate duplicate definition errors if you define the same function in two translation units. Due to code generation issues with templates, template functions are normally compiled so that multiple copies get merged into a single version, from one of the translation units. |
Brian Wood <woodbrian77@gmail.com>: Dec 18 06:35AM -0800 On Saturday, January 28, 2017 at 11:31:25 AM UTC-6, Brian Wood wrote: > If you mean there are costs for standard library implementors > and to compile times, I agree. But I don't think there's > a run-time cost for adding that function if you don't use it. I wish this would have been added to 2020 C++. Perhaps it's not too late for the next version. Brian Ebenezer Enterprises - In G-d we trust. https://webEbenezer.net |
Bonita Montero <Bonita.Montero@gmail.com>: Dec 18 04:25PM +0100 What's wrong with the static address ::what() returns ? |
Bonita Montero <Bonita.Montero@gmail.com>: Dec 18 04:32PM +0100 > Why pay for what you don't need? > If you have a std::string, and a lot of people do, you can avoid > throwing away the length by using string_view rather than char*. string_view is for integrating native memory ranges of characters with the string-facilities so that you can peformantly combine them with the usual string-facilities. But exceptions are very slow anyway. So I don't see any sense other than exception::what() to return like a normal C-string. |
"Öö Tiib" <ootiib@hot.ee>: Dec 18 09:17AM -0800 > > a run-time cost for adding that function if you don't use it. > I wish this would have been added to 2020 C++. Perhaps it's > not too late for the next version. What the what() returns is either ignored or conditionally streamed to some kind of log in most code bases I've observed. The string_view does not boost performance of neither operation. Adding another virtual method to get string_view out of exception would therefore just make binary larger as compilers can optimize virtual calls into non-virtual or even inline those but that is not done with caught exceptions. Also compilers do not optimize away virtual table entries and code of such entries of used classes AFAIK. |
Brian Wood <woodbrian77@gmail.com>: Dec 18 10:32AM -0800 On Friday, December 18, 2020 at 11:18:18 AM UTC-6, Öö Tiib wrote: > What the what() returns is either ignored or conditionally streamed > to some kind of log in most code bases I've observed. The > string_view does not boost performance of neither operation. It's true that syslog and some other loggers can't handle string_view, but by the grace of G-d we are getting some C++-based operating systems. I haven't looked at them in much depth, but I hope they will use string_view in their APIs. > virtual calls into non-virtual or even inline those but that is not done > with caught exceptions. Also compilers do not optimize away virtual > table entries and code of such entries of used classes AFAIK. How about if you use link-time optimization? Probably static exceptions will affect some of the things you mention. Brian Ebenezer Enterprises |
"Öö Tiib" <ootiib@hot.ee>: Dec 18 07:24AM -0800 > > fine, and IMHO clearer than lambdas. > I was wondering if they would be a clearer or shorter way to do > it, but agree they aren't in this case. Thanks for posting all of that. Why you were wondering? Lambdas are more sophisticated callables than functions as these can be defined inline with other code, can capture state or references to state of place of definition and do remove problems with passing and returning callables. For example function can't be made to return function pointer of its own type. The added flexibility also comes with additional boiler-plate, issues and inconveniences. Otherwise the lambdas would obsolete functions. For example recursive generic variadic lambdas are annoying to make. As you apparently needed none of benefits of lambdas but instead wanted to use weakness of those it is just interesting as exercise but lacks practical value. |
David Brown <david.brown@hesbynett.no>: Dec 18 04:59PM +0100 On 18/12/2020 16:24, Öö Tiib wrote: > As you apparently needed none of benefits of lambdas but instead wanted > to use weakness of those it is just interesting as exercise but lacks practical > value. That's what I thought when I tried it. Now I know how to make recursive lambdas, which I did not know before trying it. (The trick is not entirely unlike the CRTP.) I don't know of a good use for this sort of thing - given that recursive template functions are simpler - but it was more fun than the rest of this thread. |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Dec 17 07:53PM -0800 On 12/17/2020 12:24 PM, Bonita Montero wrote: >> They were not standard. ... > When you are bound to gcc only I used GCC, but was not bound to it. you could use these intrinsics portably |
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