blob: 8bb8d4ccc62329ef98ea44f8d9b5fbeace1d610f [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001/*----------------------------------------------------------------------------*/
Brian Silverman1a675112016-02-20 20:42:49 -05002/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
Brian Silverman26e4e522015-12-17 01:56:40 -05003/* Open Source Software - may be modified and shared by FRC teams. The code */
Brian Silverman1a675112016-02-20 20:42:49 -05004/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
Brian Silverman26e4e522015-12-17 01:56:40 -05006/*----------------------------------------------------------------------------*/
Brian Silverman1a675112016-02-20 20:42:49 -05007
Brian Silverman26e4e522015-12-17 01:56:40 -05008#pragma once
9
10// MSVC 2013 doesn't allow "= default" on move constructors, but since we are
11// (currently) only actually using the move constructors in non-MSVC situations
12// (ie, wpilibC++Devices), we can just ignore it in MSVC.
13#if !defined(_MSC_VER)
14#define DEFAULT_MOVE_CONSTRUCTOR(ClassName) \
15ClassName(ClassName &&) = default
16#else
17#define DEFAULT_MOVE_CONSTRUCTOR(ClassName)
18#endif
19
20#if (__cplusplus < 201103L)
21 #if !defined(_MSC_VER)
22 #define nullptr NULL
23 #endif
24 #define constexpr const
25#endif
26
27#if defined(_MSC_VER)
28 #define noexcept throw()
29#endif
30
31// [[deprecated(msg)]] is a C++14 feature not supported by MSVC or GCC < 4.9.
32// We provide an equivalent warning implementation for those compilers here.
33#if defined(_MSC_VER)
34 #define DEPRECATED(msg) __declspec(deprecated(msg))
35#elif defined(__GNUC__)
36 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8)
37 #define DEPRECATED(msg) [[deprecated(msg)]]
38 #else
39 #define DEPRECATED(msg) __attribute__((deprecated(msg)))
40 #endif
41#elif __cplusplus > 201103L
42 #define DEPRECATED(msg) [[deprecated(msg)]]
43#else
44 #define DEPRECATED(msg) /*nothing*/
45#endif
46
47// Provide std::decay_t when using GCC < 4.9
48#if defined(__GNUC__)
49 #if __GNUC__ == 4 && __GNUC_MINOR__ < 9
50 #include <type_traits>
51 namespace std {
52 template <class T> using decay_t = typename decay<T>::type;
53 }
54 #endif
55#endif
56
57// A struct to use as a deleter when a std::shared_ptr must wrap a raw pointer
58// that is being deleted by someone else.
59template<class T>
60struct
61NullDeleter {
62 void operator()(T *) const noexcept {};
63};
64
65#include <atomic>
66// Use this for determining whether the default move constructor has been
67// called on a containing object. This serves the purpose of allowing us to
68// use the default move constructor of an object for moving all the data around
69// while being able to use this to, for instance, chose not to de-allocate
70// a PWM port in a destructor.
71struct HasBeenMoved {
72 HasBeenMoved(HasBeenMoved&& other) {
73 other.moved = true;
74 moved = false;
75 }
76 HasBeenMoved() = default;
77 std::atomic<bool> moved{false};
78 operator bool() const { return moved; }
79};
80
81// Define make_unique for C++11-only compilers
82#if __cplusplus == 201103L
83#include <cstddef>
84#include <memory>
85#include <type_traits>
86#include <utility>
87namespace std {
88template <class T>
89struct _Unique_if {
90 typedef unique_ptr<T> _Single_object;
91};
92
93template <class T>
94struct _Unique_if<T[]> {
95 typedef unique_ptr<T[]> _Unknown_bound;
96};
97
98template <class T, size_t N>
99struct _Unique_if<T[N]> {
100 typedef void _Known_bound;
101};
102
103template <class T, class... Args>
104typename _Unique_if<T>::_Single_object make_unique(Args &&... args) {
105 return unique_ptr<T>(new T(std::forward<Args>(args)...));
106}
107
108template <class T>
109typename _Unique_if<T>::_Unknown_bound make_unique(size_t n) {
110 typedef typename remove_extent<T>::type U;
111 return unique_ptr<T>(new U[n]());
112}
113
114template <class T, class... Args>
115typename _Unique_if<T>::_Known_bound make_unique(Args &&...) = delete;
116} // namespace std
117#endif