// Copyright (c) 2015, Novartis Institutes for BioMedical Research Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Novartis Institutes for BioMedical Research Inc. // nor the names of its contributors may be used to endorse or promote // products derived from this software without specific prior written // permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include #ifndef RDKIT_RDANY_H #define RDKIT_RDANY_H #include #include #include #include #include #include "LocaleSwitcher.h" #include "RDValue.h" #include #include #include namespace RDKit { // RDValue does not dynamically create POD types (kind of like // cdiggins::any) However, it doesn't use RTTI type info // directly, it uses a companion short valued type // to determine what to do. // For unregistered types, it falls back to std::any. // The Size of an RDAny is (sizeof(double) + sizeof(short) == 10 bytes) // // For the sake of compatibility, errors throw std::bad_any_cast // // Examples: // // RDAny v(2.); // v = 1; // std::vector d; // v == d; // v.asDoubleVect().push_back(4.) // rdany_cast(v).push_back(4.) // // Falls back to std::any for non registered types // v = boost::shared_ptr(new ROMol(m)); // // Safe container for RDValue -- cleans up memory and copy constructs struct RDAny { RDValue m_value; RDAny() : m_value() {} template RDAny(const T &d) : m_value(d) {} /* explicit RDAny(bool v) : m_value(v) {} template explicit RDAny(std::vector *v) : m_value(v) {} template explicit RDAny(const boost::shared_ptr &v) : m_value(v) {} */ RDAny(const RDAny &rhs) { copy_rdvalue(m_value, rhs.m_value); } ~RDAny() { RDValue::cleanup_rdvalue(m_value); } // For easy of use: // RDAny v; // v = 2.0; // v = std::string("foo..."); RDAny &operator=(const RDAny &rhs) { copy_rdvalue(m_value, rhs.m_value); return *this; } RDAny &operator=(float d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(int d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(unsigned int d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(bool d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(const std::string &d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(const std::vector &d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(const std::vector &d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(const std::vector &d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(const std::vector &d) { RDValue::cleanup_rdvalue(m_value); m_value = d; return *this; } RDAny &operator=(const std::vector &d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); return *this; } RDAny &operator=(const std::any &d) { RDValue::cleanup_rdvalue(m_value); m_value = RDValue(d); // new std::any(d); return *this; } template RDAny &operator=(const T &d) { RDValue::cleanup_rdvalue(m_value); std::any *v = new std::any(d); m_value = RDValue(v); return *this; } }; //////////////////////////////////////////////////////////////// // rdany_cast //////////////////////////////////////////////////////////////// // Const Access template const T rdany_cast(const RDAny &d) { return rdvalue_cast(d.m_value); } // Direct access template T rdany_cast(RDAny &d) { return rdvalue_cast(d.m_value); } template typename boost::enable_if, T>::type from_rdany( const RDAny &arg) { T res; if (arg.m_value.getTag() == RDTypeTag::StringTag) { Utils::LocaleSwitcher ls; try { res = rdany_cast(arg); } catch (const std::bad_any_cast &exc) { try { res = boost::lexical_cast(rdany_cast(arg)); } catch (...) { throw exc; } } } else { res = rdany_cast(arg); } return res; } template typename boost::disable_if, T>::type from_rdany( const RDAny &arg) { return rdany_cast(arg); } } // namespace RDKit #endif