#pragma once
#ifndef __MODERN_CPP_17_H
#define __MODERN_CPP_17_H
#include "Cpp11.h"
// C++17 __has_include
#ifdef __has_include // Check if __has_include is present
# if __has_include(<optional>) // Check for a standard library
# include <optional>
# elif __has_include(<experimental/optional>) // Check for an experimental version
# include <experimental/optional>
# elif __has_include(<boost/optional.hpp>) // Try with an external library
# include <boost/optional.hpp>
# else // Not found at all
# error "Missing <optional>"
# endif
#endif
#ifdef __has_cpp_attribute // Check if __has_cpp_attribute is present
# if __has_cpp_attribute(deprecated) // Check for an attribute
# define DEPRECATED(msg) [[deprecated(msg)]]
# endif
#endif
#ifndef DEPRECATED
# define DEPRECATED(msg)
#endif
using namespace std;
// https://www.learncpp.com/cpp-tutorial/b-2-introduction-to-c17/
namespace MODERNCPP::CPP17 // C++17, nested namespace
{
class Cpp17 : public Base {
public:
explicit Cpp17() noexcept {} // cannot called implicitly
// auto return type deduction
template<typename T, typename U, typename V>
auto TemplateArgumentDeduction(T const& p_char, U const& p_int, V const& p_bool) {
return std::tuple(p_char, p_int, p_bool); // Auto type deduction from arguments
}
// using typename vs class, compile time if
template <typename T>
auto CompileTimeIf(T t) {
if constexpr (std::is_pointer_v<T>)
return *t; // deduces return type to int for T = int*
else
return t; // deduces return type to int for T = int
}
// [[ using attribute-namespace : attribute-list ]]
[[nodiscard]] int StandardAttributes(bool); // caller should read return value
DEPRECATED("Method has been deprecated")
void DeprecatedMethod() {};
long Preprocessor(unsigned);
void StaticAssert();
void StdAny();
void StdByte();
void StdFileSystem(); // alternative to boost filesystetm
void StdOptional();
void StdSharedPtr() = delete; // not fully supported until C++20
void StdVariant();
void StdConjunction();
void StdDisjunction();
void StdNegation();
void StdUncaughtExceptions();
void StructuredBindingDeclaration();
void IfSwitchInitializer();
void InlineVariable();
void FoldExpression();
void RemovedTrigraphs(); // unable to output special characters
void Utf8Literals();
void HexFloatingPointLiterals();
void TemplateDeductionConstructor();
void SpecialMathFunctions();
private:
// optional can be used as the return type of a factory that may fail
std::optional<std::string> create1(bool b) {
if (b)
return "Godzilla";
return {};
}
// std::nullopt can be used to create any (empty) std::optional
auto create2(bool b) {
return b ? std::optional<std::string>{"Godzilla"} : std::nullopt;
}
// std::reference_wrapper may be used to return a reference
auto create_ref(bool b) {
static std::string value = "Godzilla";
return b ? std::optional<std::reference_wrapper<std::string>>{value}
: std::nullopt;
}
// As of C++17, a structured binding declaration can be used to simplify splitting multiple
// returned values into separate variables:
std::tuple<int, double> returnTuple() // return a tuple that contains an int and a double
{
return std::make_tuple(5, 6.7); // use std::make_tuple() as shortcut to make a tuple to return
}
// Fold Expressions
template<typename ...Args> auto sum1(Args ...args)
{
return (args + ... + 0);
}
template<typename ...Args> auto sum2(Args ...args)
{
return (args + ...);
}
template<typename ...Args>
void FoldPrint(Args&&... args) {
(std::cout << ... << forward<Args>(args)) << '\n';
}
template<typename T, typename... Args>
void FoldPushBack(vector<T>& v, Args&&... args)
{
(v.push_back(args), ...);
}
// conjunction
// func is enabled if all Ts... have the same type as T
template<typename T, typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...) {
std::cout << "all types in pack are T\n";
}
// otherwise
template<typename T, typename... Ts>
std::enable_if_t<!std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...) {
std::cout << "not all types in pack are T\n";
}
private:
inline static const std::string inline_variable = "This is an inline variable!";
};
}
#endif