Tuesday, October 3, 2017

C++14: std::integral_constant gained an operator()

C++14 added the member function operator() to integral_constant. Integral_constant wraps a static constant. operator() returns the constants value. Here is an example:

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

integral_constant<long long, 42ll> Answer;

int main()
{
  cout << Answer()     << " ";
  cout << Answer.value << " ";
  cout <<        integral_constant<long long, 42ll>::value_type(Answer) << " ";
  cout <<        integral_constant<long long,  0ll>::value_type(Answer) << " ";
  cout << sizeof(integral_constant<long long, 42ll>::value_type)        << " ";
  cout << sizeof(integral_constant<long long, 42ll>::type      )        << " ";

  cout << endl;
  return 0;
}
// Output: 42 42 42 42 8 1
Reference: http://www.cplusplus.com/reference/type_traits/integral_constant/

C++14: std::make_unique

C++14 added the make_unique template function to construct an object and wrap a unique_ptr around it. Here is an example:

#include <memory>

int main()
{
  std::unique_ptr<int  > myInt      = std::make_unique<int  >(42);
  std::unique_ptr<int[]> myIntArray = std::make_unique<int[]>(42);
  
  return 0;
}
Reference: http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique

C++14: Tuple addressing via type

C++14 added addressing a tuple component by type. Here is an example:

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

int main()
{
  std::tuple
                                        myTuple(1, 2, 3, 4.4f, 5.5, "six");

  std::cout << std::get<int        >(myTuple) << " ";
  std::cout << std::get<long       >(myTuple) << " ";
  std::cout << std::get<short      >(myTuple) << " ";
  std::cout << std::get<float      >(myTuple) << " ";
  std::cout << std::get<double     >(myTuple) << " ";
  std::cout << std::get<std::string>(myTuple) << " ";

  std::cout << std::endl;

  return 0;
}
// Output: 1 2 3 4.4 5.5 six
Reference: http://developeradventure.blogspot.com/2013/12/c14-tuple-addressing-via-type.html

C++14: Standard user-defined literals

C++14 defined several standard user-defined literals:
operator""if          imaginary float      std::literals::complex_literals
operator""I           imaginary double  std::literals::complex_literals
operator""il          imaginary long      std::literals::complex_literals
operator""h          hours                      std::literals::chrono_literals
operator""min      minutes                  std::chrono::duration
operator""s          seconds                   std::chrono::duration
operator""ms       milliseconds           std::chrono::duration
operator""us        microseconds         std::chrono::duration
operator""ns        nanoseconds          std::chrono::duration
operator""s          string                      std::literals::string_literals


Here is an example:

#include <chrono>
#include <complex>
#include <iostream>

int main()
{
  using namespace std::complex_literals;
  std::cout << 1.1if << " ";
  std::cout << 2.2i  << " ";
  std::cout << 3il   << " ";

  using namespace std::chrono_literals;
  std::cout << std::chrono::seconds    (4h  ).count() << " ";
  std::cout << std::chrono::seconds    (5min).count() << " ";
  std::cout << std::chrono::seconds    (6s  ).count() << " ";
  std::cout << std::chrono::nanoseconds(7ms ).count() << " ";
  std::cout << std::chrono::nanoseconds(8us ).count() << " ";
  std::cout << std::chrono::nanoseconds(9ns ).count() << " ";

  using namespace std::string_literals;
  std::cout << "Hello"s << " ";

  std::cout << std::endl;
  return 0;
}
// Output: (0,1.1) (0,2.2) (0,3) 14400 300 6 7000000 8000 9 Hello
Reference: http://en.cppreference.com/w/cpp/language/user_literal

C++14: Heterogeneous lookup in associative containers

C++14 added heterogeneous lookup in associative containers. It is enabled by specifying ‘less<>’ in the container template. Here is an example:

#include <iostream>
#include <functional>
#include <set>
using namespace std;

class MyClass0
{
  int mId;
 public:
  MyClass0(int id) : mId(id) {cout << "CTOR0 ";}
  bool operator< (const MyClass0 & rhs) const
  {
    return this->mId < rhs.mId;
  }
};

class MyClass1
{
  int mId;
 public:
  MyClass1(int id) : mId(id) {cout << "CTOR1 ";}
  bool operator< (const MyClass1 & rhs) const
  {
    return this->mId < rhs.mId;
  }
};

class MyClass2
{
  int mId;
 public:
  MyClass2(int id) : mId(id) {cout << "CTOR2 ";}
  bool operator< (const MyClass2 & rhs) const
  {
    return this->mId < rhs.mId;
  }
};

int main()
{
  set<MyClass0                 > mySet0;
  set<MyClass1, less<        > > mySet1; // Allows Heterogeneous Lookup.
  set<MyClass2, less<MyClass2> > mySet2;

  set<MyClass0                 >::iterator mySet0_iter;
  set<MyClass1, less<        > >::iterator mySet1_iter;
  set<MyClass2, less<MyClass2> >::iterator mySet2_iter;

  MyClass0 myObject0_1(1);
  mySet0.insert(myObject0_1);
  mySet0_iter=mySet0.find(myObject0_1);cout<<(mySet0_iter!=mySet0.end())<<" ";
  mySet0_iter=mySet0.find(MyClass0(1));cout<<(mySet0_iter!=mySet0.end())<<" ";
  mySet0_iter=mySet0.find(1          );cout<<(mySet0_iter!=mySet0.end())<<" ";
  cout << endl;

  MyClass1 myObject1_1(1);
  mySet1.insert(myObject1_1);
  mySet1_iter=mySet1.find(myObject1_1);cout<<(mySet1_iter!=mySet1.end())<<" ";
  mySet1_iter=mySet1.find(MyClass1(1));cout<<(mySet1_iter!=mySet1.end())<<" ";
  // The following does not compile in MSVS2014.
  //mySet1_iter=mySet1.find(1          );cout<<(mySet1_iter!=mySet1.end())<<" ";
  cout << endl;

  MyClass2 myObject2_1(1);
  mySet2.insert(myObject2_1);
  mySet2_iter=mySet2.find(myObject2_1);cout<<(mySet2_iter!=mySet2.end())<<" ";
  mySet2_iter=mySet2.find(MyClass2(1));cout<<(mySet2_iter!=mySet2.end())<<" ";
  mySet2_iter=mySet2.find(1          );cout<<(mySet2_iter!=mySet2.end())<<" ";

  cout << endl;
  return 0;
}
// Output(MSVS): CTOR0 1 CTOR0 1 CTOR0 1
//               CTOR1 1 CTOR1 1
//               CTOR2 1 CTOR2 1 CTOR2 1
//
// Output(g++):  CTOR0 1 CTOR0 1 CTOR0 1
//               CTOR1 1 CTOR1 1 CTOR1 1
//               CTOR2 1 CTOR2 1 CTOR2 1
Reference: https://en.wikipedia.org/wiki/C%2B%2B14#Heterogeneous_lookup_in_associative_containers

C++14: Shared Lock Type

C++14 added a Shared Lock Type. Here is an example:

#include <iostream>
#include <mutex>
#include <shared_mutex>

int main()
{
  std::shared_timed_mutex MySharedTimedMutex;

  std::shared_lock<std::shared_timed_mutex>
                                    MySharedLock(MySharedTimedMutex);
  if (MySharedLock.owns_lock())
  {
    std::cout << "R+ ";
  }
  else
  {
    std::cout << "R- ";
  }

  std::shared_lock<std::shared_timed_mutex>
                                   MySharedLock2(MySharedTimedMutex);

  if (MySharedLock2.owns_lock())
  {
    std::cout << "R+ ";
  }
  else
  {
    std::cout << "R- ";
  }

  MySharedLock.unlock();
  MySharedLock2.unlock();

  std::unique_lock<std::shared_timed_mutex>
                                    MyUniqueLock(MySharedTimedMutex);
  if (MyUniqueLock.owns_lock())
  {
    std::cout << "W+ ";
  }
  else
  {
    std::cout << "W- ";
  }
  return 0;
}
// Output: R+ R+ W+
Reference: http://en.cppreference.com/w/cpp/thread/shared_lock/shared_lock

C++14: Shared Timed Mutex

C++14 added a shared timed mutex. You can lock something as shared (like a reader lock) or exclusive (like a writer lock). Here is an example:

#include <iostream>
#include <shared_mutex>

int main()
{
  std::shared_timed_mutex MySharedTimedMutex;

  if (MySharedTimedMutex.try_lock_shared())
  {
    std::cout << "R+ ";
  }
  else
  {
    std::cout << "R- ";
  }
  if (MySharedTimedMutex.try_lock_shared())
  {
    std::cout << "R+ ";
  }
  else
  {
    std::cout << "R- ";
  }
  if (MySharedTimedMutex.try_lock())
  {
    std::cout << "W+ ";
  }
  else
  {
    std::cout << "W- ";
  }
  MySharedTimedMutex.unlock_shared();
  MySharedTimedMutex.unlock_shared();
  if (MySharedTimedMutex.try_lock())
  {
    std::cout << "W+ ";
  }
  else
  {
    std::cout << "W- ";
  }
  return 0;
}
// Output: R+ R+ W- W+
Reference: http://en.cppreference.com/w/cpp/thread/shared_timed_mutex