Sunday, December 13, 2015

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

"Tobias Müller" <troplin@bluewin.ch>: Dec 12 07:55AM

>> I see no big difference except the increased verbosity of templates.
 
> Resulting in the template keyword spreading like a virus in your code
> with a proportional increase in compilation time and binary file size.
 
If you want static polymorphism everywhere then yes, that's the price to
pay.
Compilation will increase for sure, binary size depends. In practice you
probably won't have too many different instantiations and with better
optimization possibilities size could probably even decrease.
 
> The big difference is having dependencies on abstractions rather than
> concretions results in looser coupling and better design sausages.
 
Nothing prevents you from still having an IBar interface. Bar beeing a
template itself is orthogonal to that.
I'm not saying that runtime polymorphism is generally bad and templates
should always be preferred. But if you need the performance it's a valid
alternative for achieving DI.
 
Tobi
Christopher Pisz <nospam@notanaddress.com>: Dec 10 06:33PM -0600

The concept of dependency injection is becoming a thing where I work for
all the .NET guys. I barely understand it having never been exposed in
my C++ bubble of 1 programmer on the team for some time.
 
If I understand the programming pattern itself, it simply means to pass
dependencies at construction time as interfaces to a class. This way,
the class isn't aware of what concrete implementation it is using. Seems
like I've been doing that all along anyway...Is there more to it?
 
At least in .NET land, there seems to be some hinting at "configuring
which concrete implementation to use" that goes along with this. I guess
they do it in one of the many configuration files visual studio
generates with a project through some magic library, but I don't know.
 
Do we have something similar we can do in C++?
It seems like it would be very useful to configure a particular
implementation to use without having to recompile, especially for unit
tests when there is a desire to use a mock/proxy interface.
 
Are there any good articles to read or examples to go over that I should
be aware of? Is this a thing for us too?
 
 
--
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble", and "Islam"
So, I won't be able to see or respond to any such messages
---
Victor Bazarov <v.bazarov@comcast.invalid>: Dec 10 09:41PM -0500

On 12/10/2015 7:33 PM, Christopher Pisz wrote:
> tests when there is a desire to use a mock/proxy interface.
 
> Are there any good articles to read or examples to go over that I should
> be aware of? Is this a thing for us too?
 
Sounds like a marriage between a pimpl idiom and a factory pattern.
 
V
--
I do not respond to top-posted replies, please don't ask
Ian Collins <ian-news@hotmail.com>: Dec 11 11:00AM +1300

Mr Flibble wrote:
> Some of the idiotic things that regulars of this newsgroup still
> continue to advocate:
 
Most of what followed was debunked last time you posted it. Have you
run out of sausages?
 
--
Ian Collins
Ian Collins <ian-news@hotmail.com>: Dec 11 11:10AM +1300

Gareth Owen wrote:
 
>> Most of what followed was debunked last time you posted it. Have you
>> run out of sausages?
 
> Please do not treat the issue of running out of sausages with levity.
 
Oh I don't. I maintain multiple redundant sources to mitigate that risk.
 
--
Ian Collins
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 11 05:59AM +0100

On 12/11/2015 5:24 AM, Nobody wrote:
 
> What does this actually mean? Or rather, why doesn't wchar_t count?
 
> Admittedly, wchar_t isn't guaranteed to be Unicode. But if it isn't,
> that's usually because the platform itself doesn't support Unicode.
 
In practice wchar_t is guaranteed to be Unicode (I don't know of any
exception), but Unix-land OS APIs don't take wide string arguments.
E.g., the Unix-land "open" function takes a narrow string,
 
// http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html
int open(const char *path, int oflag, ... )
 
The corresponding function in Windows is the appropriate mode of the
all-purpose CreateFileW function, which takes wide strings or (via a
wrapper called CreateFileA) Windows ANSI-encoded narrow strings.
 
This matters both for the case where such functions are used directly
(C++ is not only for writing portable code), and for the case where one
desires to write a portable interface with system-dependent
implementation that should not need to convert encodings and do dynamic
allocation and such... An example of such an interface is the Boost
filesystem library, which will be part of C++17. It kludge-solves the
issue by requiring wide string based stream constructors in Windows, but
I think that singling out a specific OS in the specification of a
standard library component for C++, is a very very bad approach, and so
needless – it would not be a problem with core support for a syschar.
 
Cheers & hth.,
 
- Alf
David Brown <david.brown@hesbynett.no>: Dec 11 10:44AM +0100

On 10/12/15 17:41, Alf P. Steinbach wrote:
> unsigned type, as very unnecessary: just by using signed types for
> numbers, and reserving unsigned types for bitlevel stuff, it's avoided.
 
> Well, mostly. ;-)
 
OK. I know that mixing signed and unsigned can introduce subtle errors,
so I can understand if you want to avoid it. (My own use is a little
different, and I use unsigned types a lot - but then, I do low-level
programming on small embedded systems, and therefore much more "bitlevel
stuff".)
 
 
> In the single case (that I know of) where the C++ standard library
> represents a size as signed, namely "count" and "count_if", it uses the
> iterator difference type, which for pointers is "ptrdiff_t".
 
I would then say that C++ itself does not need a standard signed size
type - if you are using Posix, then you've got "ssize_t", and if you are
using "count" you have ptrdiff_t. But if you want a nicely named signed
size type for your own use, that seems fair enough.
 
 
> C++ now supports Posix, at least to some degree. In particular with
> C++11 conversions between function and data pointers, required by Posix,
> was allowed. It's up the implemention whether it's allowed.
 
Posix is not supposed to work on /all/ C++ implementations. It makes
certain requirements of the C or C++ implementation beyond the
standards. For example, it requires two's complement signed integers,
8-bit chars, and 32-bit int. So Posix has always relied on certain
implementation-dependent features of C and C++ - but they are ones that
are valid on all systems for which Posix is realistic.
 
>> dependent, in that they may not actually be 8-bit, 16-bit or 32-bit on
>> all systems, but otherwise they are standardised.
 
> No, that's not usefully system dependent.
 
I don't see system dependent as a good thing here - in fact, I see it as
a bad thing.
 
 
> That's the kind of portability that "int" offers: it's right for the
> system at hand, and yields one common source code that adapts
> automatically to the system it's compiled on.
 
I am actually much happier that you /don't/ have that. You can write
u8"Blah" and have the string as a utf8 string, or U"Blah" for a utf32
string. Plain old strings give you the default system-dependent 8-bit
character encoding, which is suitable for plain ASCII and little else.
 
If you want to write code that is tied directly to a particular OS and
its API, you can use the types that suit that OS - utf8 for *nix, utf16
for Windows (and hope that you don't fall foul of the UCS16/utf16 mess).
The types there are clear.
 
If you want to write code that is independent of the OS, you use a
cross-platform library in between so that your code can stick to a
single format (usually utf8 or utf32) and the library handles the
OS-specific part.
 
 
> Yes, but it's in the wrong direction.
 
> I was talking about casting (back) to signed, without giving the
> compiler Unsound Optimization Ideas™ based on formal UB here and there.
 
Sorry, I misread you here. Converting from signed to unsigned is
well-defined, while converting from unsigned to signed has
implementation-defined behaviour when the value cannot be represented.
It is not undefined behaviour, so there is no "compiler problem". I
don't know for sure about other compilers, but gcc (and therefore llvm,
which follows gcc in these matters) implements modulo behaviour here.
Since all signed integers in gcc are two's complement, that means the
compiler will simply re-interpret the same bit pattern as a signed
value. It would surprise me if the implementation-defined behaviour was
any different on other compilers, at least for "nice" target architectures.
 
> unsigned, exactly as you showed here, as a first step, to get
> well-defined modulo wrapping). I guess it can be done in a more elegant
> way. And not sure if it /really/ avoids the compiler problem.
 
There is no compiler problem here as far as I can see (see above). The
only issue could be implementation-defined (but not undefined) behaviour
being different on some compilers.
 
 
>> Would it make sense to put "constexpr" in the code in some cases?
 
> Not sure. Do you have something in particular in mind? I'm still at the
> stage where I only add "constexpr" where it's directly needed.
 
I was thinking for cases like "is_ascii" (though you need C++14 for the
loop - in C++11 you'd need to use recursion), and wrap_to. Basically,
using "constexpr" restricts what you can do in the function (less so in
C++14), but means that the compiler can pre-calculate it (if the
parameters are constant) and use the results in more contexts. So when
the restrictions on the features needed in the function are not a
limitation, it adds flexibility that could be useful in this sort of code.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 11 01:32PM +0100

On 12/11/2015 10:44 AM, David Brown wrote:
> cross-platform library in between so that your code can stick to a
> single format (usually utf8 or utf32) and the library handles the
> OS-specific part.
 
Consider if that was so for integers, that one needed some 3rd party
library to interface the integers with the OS API, converting back and
forth.
 
It's possible but it's just needlessly complex and inefficient.
 
 
> Sorry, I misread you here. Converting from signed to unsigned is
> well-defined, while converting from unsigned to signed has
> implementation-defined behaviour when the value cannot be represented.
 
Hm, you're right.
 
All that the function does technically then is to avoid a sillywarning
with Visual C++ 2015 update 1, but that sillywarning can instead be
turned off.
 
Grumble grumble...
 
 
> It is not undefined behaviour, so there is no "compiler problem".
 
Well, not so fast. But right, the conversion is implementation defined
behavior. Thanks, it slipped my mind!
 
 
> parameters are constant) and use the results in more contexts. So when
> the restrictions on the features needed in the function are not a
> limitation, it adds flexibility that could be useful in this sort of code.
 
C++14 sounds good, after all we're in 2015. But I'll have to experiment
to find out what Visual C++ 2015 supports. E.g. it doesn't yet (as of
update 1) support variable templates.
 
 
Cheers, & thanks,
 
- Alf
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 11 02:57PM +0100

On 12/11/2015 1:32 PM, Alf P. Steinbach wrote:
 
> C++14 sounds good, after all we're in 2015. But I'll have to experiment
> to find out what Visual C++ 2015 supports. E.g. it doesn't yet (as of
> update 1) support variable templates.
 
Unfortunately the following code does not compile with MSVC 2015 update
1 (the latest version of Visual C++) when NEWFANGLED is defined,
although it does compile with MinGW g++ 5.1.0:
 
 
<code>
#ifdef NEWFANGLED
 
template< class... Args >
constexpr
auto exactly_one_of( const Args&... args )
-> bool
{
const bool values[] = {!!args...};
int sum = 0;
for( bool const b : values ) { sum += b; }
return (sum == 1);
}
 
#else
 
inline constexpr
auto n_truths()
-> int
{ return 0; }
 
template< class... Args >
constexpr
auto n_truths( const bool first, Args const&... rest )
-> int
{ return first + n_truths( rest... ); }
 
template< class... Args >
constexpr
auto exactly_one_of( const Args&... args )
-> bool
{ return (n_truths( !!args... ) == 1); }
 

No comments: