exceptions in ngcore

This commit is contained in:
Christopher Lackner 2018-12-28 15:54:04 +01:00
parent 8e53eb46bb
commit c000160f92
5 changed files with 90 additions and 20 deletions

View File

@ -1,4 +1,4 @@
Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard' Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value'
CheckOptions: CheckOptions:
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
value: 1 value: 1

View File

@ -26,6 +26,7 @@ if(USE_PYTHON)
endif(USE_PYTHON) endif(USE_PYTHON)
install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp
exception.hpp
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)
if(ENABLE_CPP_CORE_GUIDELINES_CHECK) if(ENABLE_CPP_CORE_GUIDELINES_CHECK)

View File

@ -7,13 +7,13 @@
#include <functional> // for function #include <functional> // for function
#include <map> // for map #include <map> // for map
#include <memory> // for shared_ptr #include <memory> // for shared_ptr
#include <stdexcept> // for runtime_error
#include <string> // for string #include <string> // for string
#include <type_traits> // for declval, enable_if, false_type, is_co... #include <type_traits> // for declval, enable_if, false_type, is_co...
#include <typeinfo> // for type_info #include <typeinfo> // for type_info
#include <utility> // for move, swap, pair #include <utility> // for move, swap, pair
#include <vector> // for vector #include <vector> // for vector
#include "exception.hpp" // for UnreachableCodeException, Exception
#include "logging.hpp" // for logger #include "logging.hpp" // for logger
#include "ngcore_api.hpp" // for NGCORE_API, unlikely #include "ngcore_api.hpp" // for NGCORE_API, unlikely
#include "type_traits.hpp" // for all_of_tmpl #include "type_traits.hpp" // for all_of_tmpl
@ -37,7 +37,7 @@ namespace ngcore
// create new pointer of type T if it is default constructible, else throw // create new pointer of type T if it is default constructible, else throw
template<typename T, typename ...Rest> template<typename T, typename ...Rest>
T* constructIfPossible_impl(Rest... /*unused*/) T* constructIfPossible_impl(Rest... /*unused*/)
{ throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } { throw Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); }
template<typename T, typename= typename std::enable_if<std::is_constructible<T>::value>::type> template<typename T, typename= typename std::enable_if<std::is_constructible<T>::value>::type>
T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT
@ -140,9 +140,9 @@ namespace ngcore
#ifdef NETGEN_PYTHON #ifdef NETGEN_PYTHON
virtual void ShallowOutPython(const pybind11::object& /*unused*/) virtual void ShallowOutPython(const pybind11::object& /*unused*/)
{ throw std::runtime_error("Should not get in ShallowToPython base class implementation!"); } { throw UnreachableCodeException{}; }
virtual pybind11::object ShallowInPython() virtual pybind11::object ShallowInPython()
{ throw std::runtime_error("Should not get in ShallowFromPython base class implementation!"); } { throw UnreachableCodeException{}; }
#endif // NETGEN_PYTHON #endif // NETGEN_PYTHON
Archive& operator=(const Archive&) = delete; Archive& operator=(const Archive&) = delete;
@ -284,9 +284,9 @@ namespace ngcore
NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " + NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " +
Demangle(typeid(*ptr).name())); Demangle(typeid(*ptr).name()));
if(!IsRegistered(Demangle(typeid(*ptr).name()))) if(!IsRegistered(Demangle(typeid(*ptr).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ") throw Exception(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*ptr).name()) + Demangle(typeid(*ptr).name())
+ " not registered for archive"); + " not registered for archive");
reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get());
// if there was a true downcast we have to store more information // if there was a true downcast we have to store more information
if(reg_ptr != static_cast<void*>(ptr.get())) if(reg_ptr != static_cast<void*>(ptr.get()))
@ -404,9 +404,9 @@ namespace ngcore
NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " + NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " +
Demangle(typeid(*p).name())); Demangle(typeid(*p).name()));
if(!IsRegistered(Demangle(typeid(*p).name()))) if(!IsRegistered(Demangle(typeid(*p).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ") throw Exception(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*p).name()) + Demangle(typeid(*p).name())
+ " not registered for archive"); + " not registered for archive");
reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p)); reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p));
if(reg_ptr != static_cast<void*>(p)) if(reg_ptr != static_cast<void*>(p))
{ {
@ -427,8 +427,8 @@ namespace ngcore
return (*this) << -1 & (*p); return (*this) << -1 & (*p);
} }
else else
throw std::runtime_error(std::string("Archive error: Class ") + throw Exception(std::string("Archive error: Class ") +
Demangle(typeid(*p).name()) + " does not provide a default constructor!"); Demangle(typeid(*p).name()) + " does not provide a default constructor!");
else else
{ {
// if a pointer to a base class is archived, the class hierarchy must be registered // if a pointer to a base class is archived, the class hierarchy must be registered
@ -436,9 +436,9 @@ namespace ngcore
// implement a void DoArchive(Archive&) member function // implement a void DoArchive(Archive&) member function
// To recreate the object we need to store the true type of it // To recreate the object we need to store the true type of it
if(!IsRegistered(Demangle(typeid(*p).name()))) if(!IsRegistered(Demangle(typeid(*p).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ") throw Exception(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*p).name()) + Demangle(typeid(*p).name())
+ " not registered for archive"); + " not registered for archive");
NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer"); NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer");
return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p);
} }
@ -552,11 +552,11 @@ namespace ngcore
{ {
static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/) static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/)
{ {
throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); throw Exception("Upcast not successful, some classes are not registered properly for archiving!");
} }
static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/) static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/)
{ {
throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); throw Exception("Downcast not successful, some classes are not registered properly for archiving!");
} }
}; };
@ -568,7 +568,7 @@ namespace ngcore
try try
{ return GetArchiveRegister(Demangle(typeid(B1).name())). { return GetArchiveRegister(Demangle(typeid(B1).name())).
upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); } upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); }
catch(std::exception&) catch(const Exception&)
{ return Caster<T, Brest...>::tryUpcast(ti, p); } { return Caster<T, Brest...>::tryUpcast(ti, p); }
} }
@ -581,7 +581,7 @@ namespace ngcore
return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())). return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())).
downcaster(ti, p))); downcaster(ti, p)));
} }
catch(std::exception&) catch(const Exception&)
{ {
return Caster<T, Brest...>::tryDowncast(ti, p); return Caster<T, Brest...>::tryDowncast(ti, p);
} }

68
libsrc/core/exception.hpp Normal file
View File

@ -0,0 +1,68 @@
#ifndef NETGEN_CORE_EXCEPTION_HPP
#define NETGEN_CORE_EXCEPTION_HPP
#include <sstream> // for stringstream
#include <stdexcept> // for exception
#include <string> // for string
#include "ngcore_api.hpp" // for NGCORE_API
namespace ngcore
{
// Exception for code that shouldn't be executed
class NGCORE_API UnreachableCodeException : public std::exception
{
const char* what() const noexcept override
{
return "Shouldn't get here, something went wrong!";
}
};
// Default exception class
class NGCORE_API Exception : public std::exception
{
/// a verbal description of the exception
std::string m_what;
public:
Exception() = default;
Exception(const Exception&) = default;
Exception(Exception&&) = default;
Exception(const std::string& s) : m_what(s) {}
Exception(const char* s) : m_what(s) {}
~Exception() override = default;
Exception& operator =(const Exception&) = default;
Exception& operator =(Exception&&) noexcept = default;
/// append string to description
Exception & Append (const std::string & s) { m_what += s; return *this; }
/// append string to description
Exception & Append (const char * s) { m_what += s; return *this; }
/// verbal description of exception
const std::string & What() const { return m_what; }
/// implement virtual function of std::exception
const char* what() const noexcept override { return m_what.c_str(); }
};
// Out of Range exception
class NGCORE_API RangeException : public Exception
{
public:
/// where it occurs, index, minimal and maximal indices
RangeException (const std::string & where,
int ind, int imin, int imax) : Exception("")
{
std::stringstream str;
str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n";
Append (str.str());
}
};
// Exception used if no simd implementation is available to fall back to standard evaluation
class NGCORE_API ExceptionNOSIMD : public Exception
{ public: using Exception::Exception; };
} // namespace ngcore
#endif // NETGEN_CORE_EXCEPTION_HPP

View File

@ -2,6 +2,7 @@
#define NETGEN_CORE_NGCORE_HPP #define NETGEN_CORE_NGCORE_HPP
#include "archive.hpp" #include "archive.hpp"
#include "exception.hpp"
#include "logging.hpp" #include "logging.hpp"
#include "version.hpp" #include "version.hpp"