Skip to content

File exception.h

File List > code_source > templat > include > TempLat > util > exception.h

Go to the documentation of this file

#ifndef TEMPLAT_UTIL_EXCEPTION_H
#define TEMPLAT_UTIL_EXCEPTION_H

/* This file is part of TempLat, available at https://cosmolattice.github.io/templat .
   Copyright 2021-2026 The TempLat authors, see AUTHORS.md.
   Released under the MIT license, see LICENSE.md. */

// File info: Main contributor(s): Wessel Valkenburg, Year: 2019

#include <exception>
#include <iostream>
#include <sstream>
#include <string>

#include "TempLat/util/log/colors.h"
#include "TempLat/util/log/puttostream.h"
#include "TempLat/util/debug/stacktrace.h"

namespace TempLat
{

  inline void ExceptionArgumentUnpacker(std::stringstream &stream) { /* stop the recursion. */ }

  template <typename T, typename... Args>
  inline void ExceptionArgumentUnpacker(std::stringstream &stream, T t, Args... args)
  {
    stream << t << " ";
    ExceptionArgumentUnpacker(stream, args...);
  }

  class Exception : public std::exception
  {
  public:
    // Put public methods here. These should change very little over time.
    Exception(const char *itheWhat) : theWhat(itheWhat), strtrace(Stacktrace())
    {
      //    std::cerr << "Constructing exception: " << theWhat << "\n" << trace() << "\n";
      theStringWhat = KRED + std::string(itheWhat) + KRESET;
    };
    template <typename... Args> Exception(Args... args) : theWhat(NULL), strtrace(Stacktrace())
    {
      std::stringstream stream;
      ExceptionArgumentUnpacker(stream, args...);
      theStringWhat = KRED + stream.str() + KRESET;
    };
    const char *what() const noexcept
    {
      std::cerr << strtrace << "\n";
      return theStringWhat.length() ? theStringWhat.c_str() : theWhat;
    }
    const std::string &trace() const noexcept { return strtrace; }

  private:
    /* Put all member variables and private methods here. These may change arbitrarily. */
    const char *theWhat;
    std::string theStringWhat;
    const std::string strtrace;
  };
} // namespace TempLat

#define MakeException(name)                                                                                            \
  class name : public TempLat::Exception                                                                               \
  {                                                                                                                    \
  public:                                                                                                              \
    name(const char *iitheWhat) : TempLat::Exception(iitheWhat) {};                                                    \
    template <typename... Args> name(Args... args) : TempLat::Exception(args...) {};                                   \
  }

#endif