1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 2 // 3 // Nullable.h: Rcpp R/C++ interface class library -- SEXP container which can be NULL 4 // 5 // Copyright (C) 2015 Dirk Eddelbuettel and Daniel C. Dillon 6 // 7 // This file is part of Rcpp. 8 // 9 // Rcpp is free software: you can redistribute it and/or modify it 10 // under the terms of the GNU General Public License as published by 11 // the Free Software Foundation, either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Rcpp is distributed in the hope that it will be useful, but 15 // WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. 21 22 #ifndef Rcpp_Nullable_h 23 #define Rcpp_Nullable_h 24 25 // We looked into the safe_bool_idiom [1] but found that more trouble than is 26 // warranted here. We first and foremost want an operator SEXP() which got in 27 // the way of redefining operator bool. 28 // [1] http://www.artima.com/cppsource/safebool.html) 29 30 namespace Rcpp { 31 32 template<class T> 33 class Nullable { 34 public: 35 36 /** 37 * Empty no-argument constructor of a Nullable object 38 * 39 * Assigns (R's) NULL value, and sets validator to FALSE 40 */ Nullable()41 inline Nullable() : m_sexp(R_NilValue), m_set(false) {} 42 43 /** 44 * Template constructor of a Nullable object 45 * 46 * Assigns object, and set validator to TRUE 47 */ 48 Nullable(const T & t)49 inline Nullable(const T &t) : m_sexp(t), m_set(true) {} 50 51 /** 52 * Standard constructor of a Nullable object 53 * 54 * @param SEXP is stored 55 */ Nullable(SEXP t)56 inline Nullable(SEXP t) { 57 m_sexp = t; 58 m_set = true; 59 } 60 61 public: 62 63 /** 64 * Copy constructor for Nullable object 65 * 66 * @param SEXP is used to update internal copy 67 */ 68 inline Nullable &operator=(SEXP sexp) { 69 m_sexp = sexp; 70 m_set = true; 71 return *this; 72 } 73 74 /** 75 * operator SEXP() to return nullable object 76 * 77 * @throw 'not initialized' if object has not been set 78 */ SEXP()79 inline operator SEXP() const { 80 checkIfSet(); 81 return m_sexp; 82 } 83 84 /** 85 * get() accessor for object 86 * 87 * @throw 'not initialized' if object has not been set 88 */ get()89 inline SEXP get() const { 90 checkIfSet(); 91 return m_sexp; 92 } 93 94 /** 95 * Boolean test for usability as a T 96 */ isUsable()97 inline bool isUsable() const { 98 return m_set && !Rf_isNull(m_sexp); 99 } 100 101 /** 102 * Boolean test for NULL 103 * 104 * @throw 'not initialized' if object has not been set 105 */ isNull()106 inline bool isNull() const { 107 checkIfSet(); 108 return Rf_isNull(m_sexp); 109 } 110 111 /** 112 * Boolean test for not NULL 113 * 114 * @throw 'not initialized' if object has not been set 115 */ isNotNull()116 inline bool isNotNull() const { 117 return ! isNull(); 118 } 119 120 /** 121 * Test function to check if object has been initialized 122 * 123 */ isSet(void)124 inline bool isSet(void) const { return m_set; } 125 126 /** 127 * Returns m_sexp as a T 128 */ as()129 inline T as() { return get(); } 130 131 /** 132 * Return a clone of m_sexp as a T 133 */ clone()134 inline T clone() const { return Rcpp::clone(get()); } 135 136 private: 137 SEXP m_sexp; 138 bool m_set; 139 checkIfSet(void)140 inline void checkIfSet(void) const { 141 if (!m_set) { 142 throw ::Rcpp::exception("Not initialized"); 143 } 144 } 145 }; 146 } 147 148 #endif 149