Monday, November 27, 2017

C++11: Fixed Width Integer Macro Functions for Minimum Width Constants

C++11 added fixed width integer macro functions for minimum width constants. Here is an example:

#include <cstdint>
#include <iostream>
using namespace std;
 
int main()
{
  cout << sizeof(INT8_C   (42)) << " "; // 4
  cout << sizeof(INT16_C  (42)) << " "; // 4
  cout << sizeof(INT32_C  (42)) << " "; // 4
  cout << sizeof(INT64_C  (42)) << " "; // 8
  cout << sizeof(INTMAX_C (42)) << " "; // 8
  cout << sizeof(UINT8_C  (42)) << " "; // 4
  cout << sizeof(UINT16_C (42)) << " "; // 4
  cout << sizeof(UINT32_C (42)) << " "; // 4
  cout << sizeof(UINT64_C (42)) << " "; // 8
  cout << sizeof(UINTMAX_C(42)) << " "; // 8
 
  cout << endl;
  return 0;
}
// Output: 4 4 4 8 8 4 4 4 8 8
Reference: http://en.cppreference.com/w/cpp/types/integer

C++11: Fixed Width Integer Macro Constants

C++11 added fixed width integer macro constants. Here is an example:

#include <cstdint>
#include <iostream>
using namespace std;

int main()
{
  cout <<      INT8_MIN  << " "  ; // -128
  cout <<      INT16_MIN << " "  ; // -32768
  cout <<      INT32_MIN << " "  ; // -2147483648
  cout <<      INT64_MIN << "\n "; // -9223372036854775808
  cout << (int)INT8_MAX  << "  " ; // 127: Without cast, output was a symbol.
  cout <<      INT16_MAX << "  " ; // 32767
  cout <<      INT32_MAX << "  " ; // 2147483647
  cout <<      INT64_MAX << "  " ; // 9223372036854775807
  cout << endl;
  return 0;
}
// Output:
//    -128 -32768 -2147483648 -9223372036854775808
//     127  32767  2147483647  9223372036854775807
Reference: http://en.cppreference.com/w/cpp/types/integer

C++11: Fixed Width Integer Types

C++11 added fixed width integer types. Here is an example:

#include <cstdint>
#include <iostream>
using namespace std;

int main()
{
  cout << sizeof(int8_t       ) << " "; // 1
  cout << sizeof(int16_t      ) << " "; // 2
  cout << sizeof(int32_t      ) << " "; // 4
  cout << sizeof(int64_t      ) << " "; // 8
  cout << sizeof(int_fast8_t  ) << " "; // 1
  cout << sizeof(int_fast16_t ) << " "; // 4:fastest int at least 16 bits
  cout << sizeof(int_fast32_t ) << " "; // 4
  cout << sizeof(int_fast64_t ) << " "; // 8
  cout << sizeof(int_least8_t ) << " "; // 1
  cout << sizeof(int_least16_t) << " "; // 2:smallest int at least 16 bits
  cout << sizeof(int_least32_t) << " "; // 4
  cout << sizeof(int_least64_t) << " "; // 8
  cout << sizeof(intmax_t     ) << " "; // 8
  cout << endl;
  return 0;
}
// Output: 1 2 4 8 1 4 4 8 1 2 4 8 8
Reference: http://en.cppreference.com/w/cpp/types/integer

C++17: std::apply()

C++17 added the template function std::apply() to apply a function object to arguments from a tuple. Here is an example:


#include <iostream>
#include <tuple>

int main()
{
  std::apply([](int a, int b, int c)
             {
               std::cout << a << " " << b << " " << c << std::endl;
             },
             std::make_tuple(1, 2, 3));
  return 0;
}
// Output:: 1 2 3

Reference: http://en.cppreference.com/w/cpp/types/integer

C++11: std::tuple_cat()

C++11 added the template function std::tuple_cat() that concatenates all tuples passed to it into a single tuple. Here is an example:

#include <iostream>
#include <tuple>

int main()
{
  auto myTuple1   = std::make_tuple(1, 2);
  auto myTuple2   = std::make_tuple(3, 4);
  auto myTuple3   = std::make_tuple(5, 6);
  auto myTupleAll = std::tuple_cat(myTuple1, myTuple2, myTuple3);

  std::cout << std::get<0>(myTupleAll) << " "; // 1
  std::cout << std::get<1>(myTupleAll) << " "; // 2
  std::cout << std::get<2>(myTupleAll) << " "; // 3
  std::cout << std::get<3>(myTupleAll) << " "; // 4
  std::cout << std::get<4>(myTupleAll) << " "; // 5
  std::cout << std::get<5>(myTupleAll) << " "; // 6
  std::cout << std::endl;
  return 0;
}
// Output" 1 2 3 4 5 6
Reference: http://en.cppreference.com/w/cpp/utility/tuple/tuple_cat

C++11: std::forward_as_tuple()

C++11 added the template function std::forward_as_tuple(), which creates a tuple that can be forwarded. If the arguments are rvalues, then the tuple members are rvalue references, otherwise the tuple members are lvalue members. Here is an example:

#include <iostream>
#include <map>
#include <string>
#include <tuple>

int main()
{
  std::map<std::string, std::string> myMap;

  myMap.emplace(
    std::piecewise_construct       ,  // pair CTOR selector
    std::forward_as_tuple("four_c"),  // pair first  CTOR args
                                      //  {string(string&& other)}
    std::forward_as_tuple(4, 'c'  )); // pair second CTOR args
                                      //  {string(size_type count,
                                      //   CharT ch)}
  std::cout << myMap["four_c"] << " ";

  // The '5' and 'c' are dangling references after the first semicolon.
  auto myTupleWithRvalueReferences = std::forward_as_tuple(5, 'c');

#if 0 // The following line does not compile, 
      //   because of the '5' and 'c' dangling references above.
  myMap.emplace(
    std::piecewise_construct       ,
    std::forward_as_tuple("five_c"),
    myTupleWithRvalueReferences    );
#endif

  std::cout << myMap["five_c"] << " ";

  int  count                       = 6  ;
  char ch                          = 'c';
  auto myTupleWithLvalueReferences = std::forward_as_tuple(count, ch);

  myMap.emplace(
    std::piecewise_construct      ,
    std::forward_as_tuple("six_c"),
    myTupleWithLvalueReferences   );

  std::cout << myMap["six_c"] << " ";

  std::cout << std::endl;
  return 0;
}
// Output: cccc  cccccc
Reference: http://en.cppreference.com/w/cpp/utility/tuple/forward_as_tuple

C++11: std::tie() – tuple unpacking

The function template std::tie() allows you to unpack a tuple. Here is an example:

#include <iostream>
#include <tuple>

int main()
{
  int                                  a;
  double                               b;
  int                                  c;
  double                               d;
  std::tuple<int, double, int, double> myTuple{1, 2.2, 3, 4.4};

  std::tie(a, b, c, d) = myTuple;
  std::cout << a << " "; // 1
  std::cout << b << " "; // 2.0
  std::cout << c << " "; // 3
  std::cout << d << " "; // 4.0
  std::cout << std::endl;
  return 0;
}
// Output: 1 2.2 3 4.4
References: http://en.cppreference.com/w/cpp/utility/tuple

C++11: std::tie() – tuple packing

The function template std::tie() allows you to pack a tuple. Here is an example:

#include <iostream>
#include <tuple>

int main()
{
  int                                  a = 1  ;
  double                               b = 2.2;
  int                                  c = 3  ;
  double                               d = 4.4;
  std::tuple<int, double, int, double> myTuple;

  myTuple = std::tie(a, b, c, d);
  std::cout << std::get<0>(myTuple) << " "; // 1
  std::cout << std::get<1>(myTuple) << " "; // 2.0
  std::cout << std::get<2>(myTuple) << " "; // 3
  std::cout << std::get<3>(myTuple) << " "; // 4.0
  std::cout << std::endl;
  return 0;
}
// Output: 1 2.2 3 4.4
Reference: http://en.cppreference.com/w/cpp/utility/tuple

C++17: Function returning tuple initialization-list

C++17 allows a function to return an initialization-list for a tuple. Here is an example:

#include <iostream>
#include <tuple>

///////////////////////////////////////////////////////////////////////////////
std::tuple<int, double, int, double> returnTuple()
{
  return {1, 2.2, 3, 4.4};
}

int main()
{
  std::tuple<int, double, int, double> myTuple;

  myTuple = returnTuple();
  std::cout << std::get<0>(myTuple) << " "; // 1
  std::cout << std::get<1>(myTuple) << " "; // 2.0
  std::cout << std::get<2>(myTuple) << " "; // 3
  std::cout << std::get<3>(myTuple) << " "; // 4.0
  std::cout << std::endl;
  return 0;
}
// Output: 1 2.2 3 4.4
Reference: http://en.cppreference.com/w/cpp/utility/tuple

C++17: Structural Binding – Tuple Object

Below is an example of structurally binding a tuple object:

#include <iostream>
#include <tuple>

int main()
{
  std::tuple<int, double, int, double> myTuple{1, 2.2, 3, 4.4};

  auto [a, b, c, d] = myTuple;
  std::cout << a << " "; // 1
  std::cout << b << " "; // 2.0
  std::cout << c << " "; // 3
  std::cout << d << " "; // 4.0
  std::cout << std::endl;
  return 0;
}
// Output: 1 2.2 3 4.4
References:
http://en.cppreference.com/w/cpp/language/structured_binding
http://en.cppreference.com/w/cpp/utility/tuple

Tuesday, November 21, 2017

C++17: User-Defined Deduction Guides

User-defined deduction guides do not have to be templates.


C++17: Class Template Argument Deduction

Class template argument deduction is done only when no template parameters are given.


C++17: User-Defined Deduction Guides

User-defined deduction guides look like constructors with return types declared. They are of the following general form:

template<{TemplateParameters>ClassTemplateName(ConstructorParameters) ->
                                             ClassTemplateSpecialization;

Reference: http://en.cppreference.com/w/cpp/language/class_template_argument_deduction

C++17: Automatic Deduction Guides – Overloaded Fictional Template Function Selection

The return type of the selected fictional template function is used as the deduced class template specialization.


C++17: Fictional Template Functions

Fictional template functions return the class template type.



C++17: Automatic Deduction Guides

The automatic deduction guides are the set of fictional template functions generated by the compiler.


C++17: Automatic Deduction Guides - Fictional Template Functions

C++17 creates three kinds of fictional template functions to represent class template constructors: 1) those based on actually declared constructors; 2) one based on a hypothetical default constructor; and 3) one based on a hypothetical copy constructor.


C++17: Deduction Guides

C++17 can sometimes deduce class template parameters. To do this, C++17 uses Deduction Guides. There are two kinds of Deduction Guides: 1) Automatic Deduction Guides; and 2) User-Defined Deduction Guides.
References:

C++17: std::minmax_element()

C++17 added the algorithm std::minmax_element(), which returns iterators to both the first maximum value and the first minimum value over a range. Here is an example:

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
  std::vector<int> myVector{3, 1, 4, 1, 5, 9, 2, 6, 5};
  std::pair<std::vector<int>::iterator, std::vector<int>::iterator> minmax;

  minmax = std::minmax_element(myVector.begin(), myVector.end());

  std::cout << *minmax.first  << " "; // 1
  std::cout << *minmax.second << " "; // 9

  std::cout << std::endl;
  return 0;
}
// Output: 1 9
Reference: http://en.cppreference.com/w/cpp/algorithm/minmax_element

C++17: std::max_element() and std::min_element()

C++17 added the algorithms std::max_element() and std::min_element(), which return iterators to the first maximum or minimum value, respectively, over a range. Here is an example:

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
  std::vector<int> myVector{3, 1, 4, 1, 5, 9, 2, 6, 5};

  std::cout<<*(std::max_element(myVector.begin(),myVector.end()))<<" ";//9
  std::cout<<*(std::min_element(myVector.begin(),myVector.end()))<<" ";//1
  std::cout<<std::endl;
  return 0;
}
// Output: 9 1
References:
http://en.cppreference.com/w/cpp/algorithm/max_element
http://en.cppreference.com/w/cpp/algorithm/min_element

Monday, November 13, 2017

C++17: Class Template Argument Deduction

C++17 allows class template arguments to be deduced in certain cases. To be deduced, none of the class template arguments must be given.

C++17: std::destroy_at

C++17 added std::destroy_at() that can call the destructor of an object. Here is an example:

#include <memory>

int main()
{
  int * pInt = new int();

  *pInt = 1;

  std::destroy_at(pInt); // Destructor called, but 
                         //   memory is still allocated.

  *pInt = 2;

  delete pInt; // Destructor called, and memory is deallocated.

  // *pInt = 3; // Exception Thrown (in Debug Mode)

  return 0;
}
Reference: http://en.cppreference.com/w/cpp/memory/destroy_at

C++17: std::to_chars and std::from_chars

C++17 added std::to_chars to convert a value into a character string, and std::from_chars() to convert a character string into a value.

References:

C++17: std::visit

C++17 added the template function std::visit() that accepts a visitor, and variants; and applies the visitor to the variants.


C++17: std::search

C++17 extended std::search to use additional searching algorithms. The C++ library provides three algorithms, and the user may provide others.

References:


C++17: Node Handle

C++17 added node handles to associative containers that may be used for moves instead of copies. Here is an example:

#include <iostream>
#include <set>

int main()
{
  std::set<int> mySet{1, 2, 3};
  std::set<int> mySet2;

  std::set<int>::value_type myValue;
  //std::set<int>::node_type myNodeHandle = mySet.extract(2);
  //mySet2.insert(std::move(myNodeHandle));
  std::cout << mySet.count(1) << " ";
  std::cout << mySet.count(2) << " ";
  std::cout << mySet.count(3) << " ";

  std::cout << mySet2.count(1) << " ";
  std::cout << mySet2.count(2) << " ";
  std::cout << mySet2.count(3) << " ";

  return 0;
}
// Theoretical Output: 1 0 1 0 1 0
References:
http://en.cppreference.com/w/cpp/container/node_handle
https://stackoverflow.com/questions/39423059/when-do-i-use-node-type-with-stdmapinsert

C++17: std::launder

C++17 added the template function std::launder() to handle a corner case with placement new. Here is an example:

#include <iostream>
#include <new>

struct MyStruct
{
  const int mMyConst   ;
        int mMyVariable;
  MyStruct(int myConst, int myVariable)
  : mMyConst(myConst), mMyVariable(myVariable)
  {}
};

int main()
{
  MyStruct * pMyStruct = new MyStruct(1, 2);
  std::cout << pMyStruct->mMyConst    << " "; // Should be okay.
  std::cout << pMyStruct->mMyVariable << " "; // Should be okay.

  MyStruct * pMyStruct2 = new (pMyStruct) MyStruct(3, 4);//Using Placement New.
  std::cout << pMyStruct2->mMyConst    << " "; // Should be undefined.
  std::cout << pMyStruct2->mMyVariable << " "; // Should be undefined.

  std::cout << pMyStruct->mMyConst    << " "; // Should be undefined.
  std::cout << pMyStruct->mMyVariable << " "; // Should be undefined.

  new (pMyStruct) MyStruct(5, 6);
  std::cout << pMyStruct->mMyConst    << " "; // Should be undefined.
  std::cout << pMyStruct->mMyVariable << " "; // Should be undefined.

  std::cout << pMyStruct2->mMyConst    << " "; // Should be undefined.
  std::cout << pMyStruct2->mMyVariable << " "; // Should be undefined.

  //std::cout << std::launder(pMyStruct)->mMyConst    << " ";//Should be okay.
  //std::cout << std::launder(pMyStruct)->mMyVariable << " ";//Should be okay.

  std::cout << std::endl;
  return 0;
}
References:
http://en.cppreference.com/w/cpp/utility/launder
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0532r0.pdf

C++17: std::for_each_n

C++17 added the std::for_each_n() algorithm that takes an iterator, a count, and a function, and applies the function to the first ‘count’ elements starting at the ‘iterator’. Here is an example:

#include <algorithm>
#include <iostream>

int main()
{
  int myArray[]{1, 2, 3, 4, 5, 6, 7};

  std::for_each_n(&myArray[0], 4, [](auto & value) {value = value * value;});

  for (auto element : myArray)
  {
    std::cout << element << " ";
  }
  std::cout << std::endl;
  return 0;
}
// Output: 1 4 9 16 5 6 7
Reference: http://en.cppreference.com/w/cpp/algorithm/for_each_n

C++17: Execution Policy Types

C++17 has three execution policy types:

Class                                        Constant
-------------------------------------------  ---------
std::execution::sequenced_policy             std::execution::seq
std::execution::parallel_policy              std::execution::par
std::execution::parallel_unsequenced_policy  std::execution::par_unseq
  
These constants choose algorithm overloads with the corresponding policies.

"seq"       specifies that the algorithm must not be parallelized.
"par"       specifies that the algoritmm may      be parallelized.
"par_unseq" specifies that the algorithm may      be parallelized and
              in an unsequenced way.
References:
http://en.cppreference.com/w/cpp/algorithm/execution_policy_tag
http://en.cppreference.com/w/cpp/algorithm/execution_policy_tag_t

C++17: for (auto [key, value] : my_map) {…})

C++17 allows you to get key and values nicely in a ranged-base for loop. Here is an example:

#include <iostream>
#include <map>
#include <string>

int main()
{
  std::map<int, std::string> myMap{{1,"a"}, {2, "b"}, {3, "c"}};

  for (auto [key, value] : myMap)
  {
    std::cout << key << " " << value << " : ";
  }

  std::cout << std::endl;
  return 0;
}
// Output: 1 a : 2 b : 3 c :
Reference: https://www.infoq.com/news/2017/10/cpp-17-herb-sutter-interview

Monday, November 6, 2017

C++17: std::transform_inclusive_scan()

C++17 added std::transform_inclusive_scan(). This is the same as std::inclusive_scan(), except a unary function is first applied to each input item. Here is an example (simulated on C++14):

#include <iostream>
#include <vector>

namespace std17
{
  template<class InputIt        , class OutputIt      ,
           class BinaryOperation, class UnaryOperation>
  OutputIt transform_inclusive_scan(InputIt         first    ,
                                    InputIt         last     ,
                                    OutputIt        d_first  ,
                                    BinaryOperation binary_op,
                                    UnaryOperation  unary_op )
  {
    *d_first = unary_op(*first);
    first++;
    d_first++;
    for (auto iter = first; iter != last; iter++)
    {
      *d_first = binary_op(unary_op(*iter), *(d_first - 1));
      d_first++;
    }
    return d_first;
  }
}
int main()
{
  std::vector<int> myInputVector{1, 2, 3, 4, 5};
  std::vector<int> myOutputVector(5);

  std17::transform_inclusive_scan(myInputVector.begin(),
                                  myInputVector.end()  ,
                                  myOutputVector.begin(),
                                  [](auto a, auto b) {return a + b;},
                                  [](auto a) {return a * a;});
  for (auto item : myOutputVector) 
  {
    std::cout << item << " ";
  }
  std::cout << std::endl;
  return 0;
}
// Output: 1 5 14 30 55
Reference: http://en.cppreference.com/w/cpp/algorithm/transform_inclusive_scan

C++17: std::inclusive_scan()

C++17 added std::inclusive_scan(), which accepts a sequential input container and a sequential output container and iterates throught the input container while writing to the output container result of a binary operation on the previous result with the current input item. By default, the binary operation is addition, and the output container ends up with the integration of the input container. Here is an example (simulated with C++14):

#include <iostream>
#include <vector>

namespace std17
{
  template<class InputIt, class OutputIt>
  OutputIt inclusive_scan(InputIt first, InputIt last, OutputIt d_first)
  {
    *d_first = *first;
    first++;
    d_first++;
    for (auto iter = first; iter != last; iter++)
    {
      *d_first = *iter + *(d_first - 1);
      d_first++;
    }
    return d_first;
  }
}

int main()
{
  std::vector<int> myInputVector{1, 2, 3, 4, 5};
  std::vector<int> myOutputVector(5);

  std17::inclusive_scan(myInputVector.begin() ,
                        myInputVector.end()   ,
                        myOutputVector.begin());
  for (auto item : myOutputVector) 
  {
    std::cout << item << " ";
  }
  std::cout << std::endl;
  return 0;
}
// Output: 1 3 6 10 15
References:
http://en.cppreference.com/w/cpp/algorithm/inclusive_scan
http://www.modernescpp.com/index.php/c-17-new-algorithm-of-the-standard-template-library

C++17: std::transform_reduce()

C++17 added std:: transform_reduce, which applies a functor, then reduces. The default functor is multiplication. Here is an example (simulated with C++14):

#include <iostream>
#include <vector>
 
namespace std17
{
  template<class InputIt, class T, class BinaryOp, class UnaryOp>
  T transform_reduce(InputIt  first   ,
                     InputIt  last    ,
                     T        init    ,
                     BinaryOp binop   ,
                     UnaryOp  unary_op)
  {
    T generalizedSum = init;
    for (auto iter = first; iter != last; iter++)
    {
      generalizedSum = binop(unary_op(*iter), generalizedSum);
    }
    return generalizedSum;
  }
}
 
int main()
{
  std::vector<int> myInputVector{1, 2, 3, 4, 5};
  int              result;
 
  result = std17::transform_reduce(myInputVector.begin(),
                                   myInputVector.end()  ,
                                   0                    ,
                                  [](auto a, auto b) {return a + b;},
                                  [](auto a        ) {return a * a;});
  std::cout << result << std::endl;
  return 0;
}
// Output: 55
Reference: http://en.cppreference.com/w/cpp/algorithm/transform_reduce

C++17: std::reduce()

C++17 added std::reduce(), which applies applies a binary operation on a range of elements. The default binary operation is addition. Here is an example (simulated with C++14):

#include <iostream>
#include <vector>

namespace std17
{
  template<class InputIt>
  typename std::iterator_traits<InputIt>::value_type
  reduce(InputIt first, InputIt last)
  {
    std::iterator_traits<InputIt>::value_type sum =
                 std::iterator_traits<InputIt>::value_type();
    for (auto iter = first; iter != last; iter++)
    {
      sum = sum + *iter;
    }
    return sum;
  }
}

int main()
{
  std::vector<int> myInputVector{1, 2, 3, 4, 5};
  int              result;

  result = std17::reduce(myInputVector.begin() ,
                         myInputVector.end()   );

  std::cout << result << " ";
  std::cout << std::endl;
  return 0;
}
// Output: 15
Reference: http://en.cppreference.com/w/cpp/algorithm/reduce

C++17: New Headers

C++17 added the following headers:

<any>
<execution>
<memory_resource>
<optional>
<string_view>
<variant>
Reference: http://en.cppreference.com/w/cpp/header

C++: SFINAE

SFINAE stands for “Substitution Failure is Not an Error”. When deducing which template function to use, if the compiler tries one template function, and if the substitution of template parameters is a problem; instead of the compiler declaring an error and stopping, the compiler tries the remaining template functions.

References:

C++17: std::gcd() and std::lcm()

C++17 added the greatest common divisor (GCD) function and the least common multiple (LCM) function.

#include 
#include 

int main()
{
  std::cout << std::gcd( 0, 10) << " "; // 10 
  std::cout << std::gcd( 1, 10) << " "; //  1
  std::cout << std::gcd( 2, 10) << " "; //  2
  std::cout << std::gcd( 3, 10) << " "; //  1
  std::cout << std::gcd( 4, 10) << " "; //  2
  std::cout << std::gcd( 5, 10) << " "; //  5
  std::cout << std::gcd( 6, 10) << " "; //  2
  std::cout << std::gcd( 7, 10) << " "; //  1
  std::cout << std::gcd( 8, 10) << " "; //  2
  std::cout << std::gcd( 9, 10) << " "; //  1
  std::cout << std::gcd(10, 10) << " "; // 10

  std::cout << ": ";

  std::cout << std::lcm( 0, 10) << " "; //  0 
  std::cout << std::lcm( 1, 10) << " "; // 10
  std::cout << std::lcm( 2, 10) << " "; // 10
  std::cout << std::lcm( 3, 10) << " "; // 30
  std::cout << std::lcm( 4, 10) << " "; // 20
  std::cout << std::lcm( 5, 10) << " "; // 10
  std::cout << std::lcm( 6, 10) << " "; // 30
  std::cout << std::lcm( 7, 10) << " "; // 70
  std::cout << std::lcm( 8, 10) << " "; // 40
  std::cout << std::lcm( 9, 10) << " "; // 90
  std::cout << std::lcm(10, 10) << " "; // 10

  std::cout << std::endl;
  return 0;
}
// Output: 10 1 2 1 2 5 2 1 2 1 10 : 0 10 10 30 20 10 30 70 40 90 10
References:
http://en.cppreference.com/w/cpp/numeric/gcd
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0295r0.pdf

C++17: C++17 is based on C11 instead of C99.

C++17 is based on C11 instead of C99.


C++17: std::clamp()

C++17 added the template function std::clamp() is a combination of std::max() and std::min(). Here is an example:

#include <algorithm>
#include <iostream>

int main()
{
  //                      Value Min Max
  std::cout << std::clamp( 5   ,  0, 10) << " "; //  5
  std::cout << std::clamp(-5   ,  0, 10) << " "; //  0
  std::cout << std::clamp(20   ,  0, 10) << " "; // 10

  std::cout << std::endl;
  return 0;
}
// Output: 5 0 10
Reference: https://stackoverflow.com/questions/38060436/what-are-the-new-features-in-c17

C++17: The register keyword was removed.

C++17 removed the register keyword. This keyword used to be used to hint to the compiler that a local variable is used so much that it would be nice to use a CPU Register for it instead of the stack.