From faf62cf8af49ea8be4dff761b0a8b60ca8259e58 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 13 Aug 2014 03:08:00 +0200 Subject: [PATCH] DOC: start a page with C++11 notes (here: about type conversion) note down some results found out during the C++11 transition. There is now a clear distinction between automatic type conversion and the ability to construct a new instance --- doc/technical/code/c++11.txt | 94 ++++++++++++++++++++++++++++++++++++ research/try.cpp | 34 ++----------- 2 files changed, 97 insertions(+), 31 deletions(-) create mode 100644 doc/technical/code/c++11.txt diff --git a/doc/technical/code/c++11.txt b/doc/technical/code/c++11.txt new file mode 100644 index 000000000..52883e7c2 --- /dev/null +++ b/doc/technical/code/c++11.txt @@ -0,0 +1,94 @@ +Transition to C++11 +=================== + +_this page is a notepad for topics and issues related to the new C++ standard_ + +.the state of affairs +In Lumiera, we used a contemporary coding style right from start -- whenever the actual +language and compiler support wasn't ready for what we consider _state of the craft_, we +amended deficiencies by rolling our own helper facilities, with a little help from Boost. +Thus there was no urge for us to adopt the new language standard; we could simply wait for +the compiler support to mature. In spring 2014, finally, we were able to switch our codebase +to C++11 with minimal effort. Following this switch, we're now able to reap the benefits of +this approach; we may now gradually replace our sometimes clunky helpers and workarounds +with the smooth syntax of the ``new language'' -- without being forced to learn or adopt +an entirely new coding style, since that style isn't exactly new for us. + +Conceptual Changes +------------------ +At some places we'll have to face modest conceptual changes though. + +Automatic Type Conversions +~~~~~~~~~~~~~~~~~~~~~~~~~~ +The notion of a type conversion is more precise and streamlined now. With the new standard, +we have to distinguish between + +. type relations, like being the same type (e.g. in case of a template instantiation) or a subtype. +. the ability to convert to a target type +. the ability to construct an instance of the target type + +The conversion really requires help from the source type to be performed automatically: it needs +to expose an explicit conversion operator. This is now clearly distinguished from the construction +of a new value, instance or copy with the target type. This _ability to construct_ is a way weaker +condition than the _ability to convert_, since construction never happens out of the blue. Rather +it happens in a situation, where the _usage context_ prompts to create a new value with the target +type. For example, we invoke a function with value arguments of the new type, but provide a value +or reference of the source type. + +Please recall, C++ always had, and still has that characteristic ``fixation'' on the act +of copying things. Maybe, 20 years ago that was an oddity -- yet today this approach is highly +adequate, given the increasing parallelism of modern hardware. If in doubt, we should always +prefer to work on a private copy. Pointers aren't as ``inherently efficient'' as they were +20 years ago. + +[source,c++] +-------------------------------------------------------------------------- +#include +#include +#include + +using std::function; + +using std::string; +using std::cout; +using std::endl; + + +uint +funny (char c) +{ + return c; +} + +using Funky = function; // <1> + +int +main (int, char**) + { + Funky fun(funny); // <2> + Funky empty; // <3> + + cout << "ASCII 'A' = " << fun('A'); + cout << " defined: " << bool(fun) // <4> + << " undefd; " << bool(empty) + << " bool-convertible: " << std::is_convertible::value // <5> + << " can build bool: " << std::is_constructible::value // <6> + << " bool from string: " << std::is_constructible::value; // <7> +-------------------------------------------------------------------------- +<1> a new-style type definition (type alias) +<2> a function object can be _constructed_ from `funny`, which is a reference + to the C++ language function entity +<3> a default constructed function object is in unbound (invalid) state +<4> we can explicitly _convert_ any function object to `bool` by _constructing_ a Bool value. + This is idiomatic C usage to check for the validity of an object. In this case, the _bound_ + function object yields `true`, while the _unbound_ function object yields `false` +<5> but the function object is _not automatically convertible_ to bool +<6> yet it is possible to _construct_ a `bool` from a funktor (we just did that) +<7> while it is not possible to _construct_ a bool from a string (we'd need to interpret and + parse the string, which mustn't be confused with a conversion) + +This example prints the following output:: + + ASCII 'A' = 65 defined: 1 undefd; 0 bool-convertible: 0 can build bool: 1 bool from string: 0 + + diff --git a/research/try.cpp b/research/try.cpp index dc1aca86d..9a55000cd 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -24,55 +24,27 @@ // 12/11 - how to detect if string conversion is possible? // 1/12 - is partial application of member functions possible? // 5/14 - c++11 transition: detect empty function object +// 7/14 - c++11 transition: std hash function vs. boost hash /** @file try.cpp - ** Investigation: empty and unbound function objects. - ** Since \c std::function is bool convertible, it should be possible to detect an empty or - ** unbound functor object and record this state in a VTable. Actually this approach used to - ** work with tr1::function objects. But it ceased to work after switching to c++11 - ** - ** The reason is the more concise meaning of \em convertibility with C++11 -- now, an - ** automatic conversion is required; thus what we need is rather the ability to \em construct - ** our target type from the given source explicitly, which is a weaker requirement. + ** Investigation: how to supply a hash function for custom types ** */ -#include -#include +//#include #include -//using std::placeholders::_1; -//using std::placeholders::_2; -using std::function; -using std::bind; - using std::string; using std::cout; using std::endl; -uint -funny (char c) -{ - return c; -} - -using FUC = function; int main (int, char**) { - FUC fun(funny); - FUC empty; - - cout << "ASCII 'A' = " << fun('A'); - cout << " defined: " << bool(fun) - << " undefd; " << bool(empty) - << " bool-convertible: " << std::is_convertible::value - << " can build bool: " << std::is_constructible::value - << " bool from string: " << std::is_constructible::value; cout << "\n.gulp.\n";