diff --git a/aidge_export_cpp/__init__.py b/aidge_export_cpp/__init__.py
index 26fbb739104cc032b3523c59b858a1049735eba0..d77c2e3672c3b17ca25d06125fa505f1c950e055 100644
--- a/aidge_export_cpp/__init__.py
+++ b/aidge_export_cpp/__init__.py
@@ -2,6 +2,7 @@ r"""
 Aidge Export for CPP standalone projects
 
 """
+from .export_registry import ExportLibCpp
 
 from .operators import *
 from collections import defaultdict
diff --git a/aidge_export_cpp/export.py b/aidge_export_cpp/export.py
index 2a535ddd4a355560e9037b6567cdb90a52c66df3..8fbb0733a7b4a2f3cf36193029b54b30df6aebdf 100644
--- a/aidge_export_cpp/export.py
+++ b/aidge_export_cpp/export.py
@@ -13,6 +13,7 @@ from aidge_core.export_utils.code_generation import *
 from aidge_export_cpp.utils import (ROOT, OPERATORS_REGISTRY, supported_operators)
 from aidge_export_cpp.utils.converter import numpy_dtype2ctype
 import aidge_export_cpp.operators
+from aidge_export_cpp import ExportLibCpp
 from aidge_export_cpp.utils.generation import *
 from aidge_export_cpp.memory import *
 
@@ -50,9 +51,8 @@ def export(export_folder_name, graphview, scheduler, mem_wrapping=False):
     list_forward_nodes = scheduler.get_static_scheduling()
 
     for node in list_forward_nodes:
-        if node.type() in supported_operators():
-            op = OPERATORS_REGISTRY[node.type()](node)
-
+        if ExportLibCpp.exportable(node):
+            op = ExportLibCpp.get_export_node(node)
             # For configuration files
             list_configs = op.export(dnn_folder, list_configs)
 
diff --git a/aidge_export_cpp/operators.py b/aidge_export_cpp/operators.py
index 6c16f9ec45d0a1bc008ca0302f163f4a734d9dca..8216b145579492eef54a2083770754eb102559a3 100644
--- a/aidge_export_cpp/operators.py
+++ b/aidge_export_cpp/operators.py
@@ -3,39 +3,39 @@ import shutil
 import numpy as np
 from pathlib import Path
 from jinja2 import Environment, FileSystemLoader
-
-from aidge_core import ExportNode, ExportNodeCpp
-from aidge_core.export_utils.code_generation import *
-from aidge_export_cpp.utils import ROOT, operator_register
+from aidge_core.export_utils import ExportNode, ExportNodeCpp, operator_register, generate_str, generate_file
+from aidge_export_cpp.utils import ROOT
 from aidge_export_cpp.utils.converter import numpy_dtype2ctype
 from aidge_export_cpp.utils.generation import *
-
+from aidge_export_cpp import ExportLibCpp
 ##############################################
 ################### Utils ####################
 ##############################################
 
-def get_node_parents(node):
-    parents = []
-    for parent in node.get_parents():
-        if parent.type() != "Producer":
-            parents.append(parent)
-    return parents
 
-def get_producer_parents(node):
-    parents = []
-    for parent in node.get_parents():
-        if parent.type() == "Producer":
-            parents.append(parent)
-    return parents
+# def get_node_parents(node):
+#     parents = []
+#     for parent in node.get_parents():
+#         if parent.type() != "Producer":
+#             parents.append(parent)
+#     return parents
+
+
+# def get_producer_parents(node):
+#     parents = []
+#     for parent in node.get_parents():
+#         if parent.type() == "Producer":
+#             parents.append(parent)
+#     return parents
 
 
 ##############################################
 ############## Export functions ##############
 ##############################################
 
-def export_params(name:str,
+def export_params(name: str,
                   array: np.ndarray,
-                  filepath:str):
+                  filepath: str):
 
     # Get directory name of the file
     dirname = os.path.dirname(filepath)
@@ -47,9 +47,9 @@ def export_params(name:str,
     generate_file(
         filepath,
         str(ROOT / "templates" / "data" / "parameters.jinja"),
-        name = name,
-        data_t = numpy_dtype2ctype(array.dtype),
-        values = array.tolist()
+        name=name,
+        data_t=numpy_dtype2ctype(array.dtype),
+        values=array.tolist()
     )
 
 
@@ -58,17 +58,17 @@ def export_params(name:str,
 ##############################################
 
 
-@operator_register("Producer")
+@operator_register(ExportLibCpp, "Producer")
 class ProducerCPP(ExportNode):
 
     def __init__(self, node):
         super().__init__(node)
         self.values = np.array(self.operator.get_output(0))
 
-        if len(self.values.shape) == 4: # Note: export in HWC
+        if len(self.values.shape) == 4:  # Note: export in HWC
             self.values = np.transpose(self.values, (0, 2, 3, 1))
 
-    def export(self, export_folder:Path, list_configs:list):
+    def export(self, export_folder: Path, list_configs: list):
 
         list_configs.append(f"parameters/{self.attributes['name']}.h")
         export_params(
@@ -78,26 +78,36 @@ class ProducerCPP(ExportNode):
 
         return list_configs
 
-    def forward(self, list_actions:list):
+    def forward(self, list_actions: list):
         # A Producer does nothing during forward
         return list_actions
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
 
-
-@operator_register("ReLU")
+@operator_register(ExportLibCpp, "ReLU")
 class ReLUCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
         self.attributes["activation"] = "Rectifier"
         self.attributes["rescaling"] = "NoScaling"
-        self.config_template = str(ROOT / "templates" / "configuration" / "activation_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "activation_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "activation_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "activation_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "activation.hpp"),
         ]
-
-
-@operator_register("Conv")
+    @staticmethod
+    def compatible(cls, node):
+        for idx, parent_node_in_id in node.inputs():
+            parent_node, _ = parent_node_in_id
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
+
+@operator_register(ExportLibCpp, "Conv")
 class ConvCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
@@ -106,84 +116,116 @@ class ConvCPP(ExportNodeCpp):
         self.attributes["padding"] = [0, 0]
         self.attributes["activation"] = "Linear"
         self.attributes["rescaling"] = "NoScaling"
-        self.config_template = str(ROOT / "templates" / "configuration" / "convolution_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "convolution_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "convolution_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "convolution_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "convolution.hpp"),
             str(ROOT / "kernels" / "macs.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
+
 
 
-@operator_register("PaddedConv")
+@operator_register(ExportLibCpp, "PaddedConv")
 class PaddedConvCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
         # TODO find a way to retrive attr for meta op
         for n in self.operator.get_micro_graph().get_nodes():
             if n.type() == "Pad":
-                self.attributes["padding"] = n.get_operator().attr.begin_end_borders
+                self.attributes["padding"] = n.get_operator(
+                ).attr.begin_end_borders
             if n.type() == "Conv":
-                self.attributes["kernel_dims"]   = n.get_operator().attr.kernel_dims
-                self.attributes["stride_dims"]   = n.get_operator().attr.stride_dims
-                self.attributes["dilation_dims"] = n.get_operator().attr.dilation_dims
+                self.attributes["kernel_dims"] = n.get_operator(
+                ).attr.kernel_dims
+                self.attributes["stride_dims"] = n.get_operator(
+                ).attr.stride_dims
+                self.attributes["dilation_dims"] = n.get_operator(
+                ).attr.dilation_dims
         self.attributes["activation"] = "Linear"
         self.attributes["rescaling"] = "NoScaling"
-        self.config_template = str(ROOT / "templates" / "configuration" / "convolution_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "convolution_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "convolution_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "convolution_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "convolution.hpp"),
             str(ROOT / "kernels" / "macs.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
-@operator_register("Add")
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
+
+@operator_register(ExportLibCpp, "Add")
 class AddCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
         self.attributes["elemwise_op"] = "Add"
         self.attributes["activation"] = "Linear"
         self.attributes["rescaling"] = "NoScaling"
-        self.config_template = str(ROOT / "templates" / "configuration" / "elemwise_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "elemwise_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "elemwise.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
 
-@operator_register("Sub")
+@operator_register(ExportLibCpp, "Sub")
 class SubCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
         self.attributes["elemwise_op"] = "Sub"
         self.attributes["activation"] = "Linear"
         self.attributes["rescaling"] = "NoScaling"
-        self.config_template = str(ROOT / "templates" / "configuration" / "elemwise_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "elemwise_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "elemwise.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
 
-@operator_register("Mul")
+
+@operator_register(ExportLibCpp, "Mul")
 class MulCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
         self.attributes["elemwise_op"] = "Mul"
         self.attributes["activation"] = "Linear"
         self.attributes["rescaling"] = "NoScaling"
-        self.config_template = str(ROOT / "templates" / "configuration" / "elemwise_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "elemwise_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "elemwise.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
 
-@operator_register("MaxPooling")
+@operator_register(ExportLibCpp, "MaxPooling")
 class MaxPoolCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
@@ -194,37 +236,50 @@ class MaxPoolCPP(ExportNodeCpp):
         self.attributes["pool_type"] = "Max"
         self.attributes["activation"] = "Linear"
 
-        self.config_template = str(ROOT / "templates" / "configuration" / "pooling_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "pooling_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "pooling.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
 
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
 
-@operator_register("PaddedMaxPooling")
+@operator_register(ExportLibCpp, "PaddedMaxPooling")
 class PaddedMaxPoolCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
         for n in self.operator.get_micro_graph().get_nodes():
             if n.type() == "Pad":
-                self.attributes["padding"] = n.get_operator().attr.begin_end_borders
+                self.attributes["padding"] = n.get_operator(
+                ).attr.begin_end_borders
             if n.type() == "MaxPooling":
-                self.attributes["kernel_dims"] = n.get_operator().attr.kernel_dims
-                self.attributes["stride_dims"] = n.get_operator().attr.stride_dims
+                self.attributes["kernel_dims"] = n.get_operator(
+                ).attr.kernel_dims
+                self.attributes["stride_dims"] = n.get_operator(
+                ).attr.stride_dims
         self.attributes["pool_type"] = "Max"
         self.attributes["activation"] = "Linear"
 
-        self.config_template = str(ROOT / "templates" / "configuration" / "pooling_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "pooling_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "pooling.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
 
-@operator_register("GlobalAveragePooling")
+@operator_register(ExportLibCpp, "GlobalAveragePooling")
 class GlobalAveragePoolCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
@@ -240,26 +295,35 @@ class GlobalAveragePoolCPP(ExportNodeCpp):
         self.attributes["pool_type"] = "Average"
         self.attributes["activation"] = "Linear"
 
-        self.config_template = str(ROOT / "templates" / "configuration" / "pooling_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "pooling_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "pooling.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW
 
-
-@operator_register("FC")
+@operator_register(ExportLibCpp, "FC")
 class FcCPP(ExportNodeCpp):
     def __init__(self, node):
         super().__init__(node)
         self.attributes["activation"] = "Linear"
         self.attributes["rescaling"] = "NoScaling"
-        self.config_template = str(ROOT / "templates" / "configuration" / "fullyconnected_config.jinja")
-        self.forward_template = str(ROOT / "templates" / "kernel_forward" / "fullyconnected_forward.jinja")
+        self.config_template = str(
+            ROOT / "templates" / "configuration" / "fullyconnected_config.jinja")
+        self.forward_template = str(
+            ROOT / "templates" / "kernel_forward" / "fullyconnected_forward.jinja")
         self.include_list = []
         self.kernels_to_copy = [
             str(ROOT / "kernels" / "fullyconnected.hpp"),
             str(ROOT / "kernels" / "macs.hpp"),
             str(ROOT / "kernels" / "activation.hpp"),
         ]
+    @classmethod
+    def exportable(cls, node):
+        return True # TODO add check i/o NCHW