// Copyright 2017 <Biagio Festa>
#include <iostream>
#include <type_traits>

struct CriticalError : std::true_type {
  static constexpr bool is_critical = true;
};

struct Warning : std::false_type {
  static constexpr bool is_critical = false;
};

template<typename ErrorPolicy>
void foo() {
  if constexpr (ErrorPolicy::is_critical) {
      std::cout << "Critical\n";
    } else {
    std::cout << "NotCritical\n";
  }
  
  if constexpr (std::is_base_of<std::true_type, ErrorPolicy>::value) {
      std::cout << "Critical\n";
    } else {
    std::cout << "NotCritical\n";
  }
  // ...
}

int main(int argc, char *argv[]) {
  foo<CriticalError>();
  foo<Warning>();
  return 0;
}
