#ifndef {{main_header_guard}}
#define {{main_header_guard}}

// {{project}} namespace start and stop defines
#define {{project_namespace_start}} namespace {{project}} {
#define {{project_namespace_stop}} }

// {{snake_case}} namespace start and stop defines
#define {{op_namespace_start}} namespace {{snake_case}} {
#define {{op_namespace_stop}} }

{{project_namespace_start}}
{{op_namespace_start}}

// General definition of the {{op_name}} op, which will be specialised in:
//   - {{cpp_header_file}} for CPUs
//   - {{cuda_header_file}} for CUDA devices
// Concrete template instantions of this class are provided in:
//   - {{cpp_source_file}} for CPUs
//   - {{cuda_source_file}} for CUDA devices
{% set class_template = op_type_attrs | map(attribute="name") | list -%}
{% set class_template = ["Device"] + class_template  -%}
{% set class_template = class_template | format_list("typename %s") | join(", ") -%}
{% set class_template = "template <" + class_template + ">" -%}

{{ class_template }}
class {{op_name}} {};

{{op_namespace_stop}}
{{project_namespace_stop}}

#endif // #ifndef {{main_header_guard}}