From 857cdfc4c547b5d6020d28ee111ac4501a842777 Mon Sep 17 00:00:00 2001
From: William F Godoy <williamfgc@yahoo.com>
Date: Tue, 1 Aug 2017 17:49:52 -0400
Subject: [PATCH] Started adding support for Attributes

---
 source/adios2/ADIOSMacros.h          |  20 ++++
 source/adios2/core/Attribute.h       |  48 +++++++++
 source/adios2/core/Attribute.tcc     |  41 ++++++++
 source/adios2/core/AttributeBase.cpp |  22 +++++
 source/adios2/core/AttributeBase.h   |  39 ++++++++
 source/adios2/core/IO.cpp            |  40 +++++---
 source/adios2/core/IO.h              | 104 +++++++++++++++++---
 source/adios2/core/IO.inl            |  17 ++--
 source/adios2/core/IO.tcc            | 141 ++++++++++++++++++++++++++-
 source/adios2/core/Variable.h        |   2 +-
 source/adios2/core/Variable.tcc      |   2 +-
 11 files changed, 437 insertions(+), 39 deletions(-)
 create mode 100644 source/adios2/core/Attribute.h
 create mode 100644 source/adios2/core/Attribute.tcc
 create mode 100644 source/adios2/core/AttributeBase.cpp
 create mode 100644 source/adios2/core/AttributeBase.h

diff --git a/source/adios2/ADIOSMacros.h b/source/adios2/ADIOSMacros.h
index f3043732b..f15756cac 100644
--- a/source/adios2/ADIOSMacros.h
+++ b/source/adios2/ADIOSMacros.h
@@ -8,6 +8,8 @@
 #ifndef ADIOS2_ADIOSMACROS_H
 #define ADIOS2_ADIOSMACROS_H
 
+#include <string>
+
 #include "adios2/ADIOSTypes.h"
 // The ADIOS_FOREACH_TYPE_1ARG macro assumes the given argument is a macro which
 // takes a single argument that is a type and then inserts the given MACRO for
@@ -49,6 +51,8 @@
     MACRO(unsigned int)                                                        \
     MACRO(long int)                                                            \
     MACRO(unsigned long int)                                                   \
+    MACRO(long long int)                                                       \
+    MACRO(unsigned long long int)                                              \
     MACRO(float)                                                               \
     MACRO(double)
 
@@ -62,4 +66,20 @@
     MACRO(float)                                                               \
     MACRO(double)
 
+#define ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(MACRO)                              \
+    MACRO(std::string)                                                         \
+    MACRO(char)                                                                \
+    MACRO(unsigned char)                                                       \
+    MACRO(short)                                                               \
+    MACRO(unsigned short)                                                      \
+    MACRO(int)                                                                 \
+    MACRO(unsigned int)                                                        \
+    MACRO(long int)                                                            \
+    MACRO(unsigned long int)                                                   \
+    MACRO(long long int)                                                       \
+    MACRO(unsigned long long int)                                              \
+    MACRO(float)                                                               \
+    MACRO(double)                                                              \
+    MACRO(long double)
+
 #endif /* ADIOS2_ADIOSMACROS_H */
diff --git a/source/adios2/core/Attribute.h b/source/adios2/core/Attribute.h
new file mode 100644
index 000000000..7ed3cc779
--- /dev/null
+++ b/source/adios2/core/Attribute.h
@@ -0,0 +1,48 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Attribute.h : template class
+ *
+ *  Created on: Aug 1, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_ATTRIBUTE_H_
+#define ADIOS2_CORE_ATTRIBUTE_H_
+
+#include "adios2/core/AttributeBase.h"
+
+namespace adios2
+{
+/** @brief Attributes provide complementary information to IO Variables*/
+template <class T>
+class Attribute : public AttributeBase
+{
+
+public:
+    const T *m_DataArray = nullptr;
+    T m_DataValue;
+
+    /**
+     * Data array constructor
+     * @param name
+     * @param data
+     * @param elements
+     */
+    Attribute<T>(const std::string &name, const T *data, const size_t elements);
+
+    /**
+     * Single value constructor
+     * @param name
+     * @param data
+     * @param elements
+     */
+    Attribute<T>(const std::string &name, const T &data);
+
+    ~Attribute<T>() = default;
+};
+
+} // end namespace adios2
+
+#endif /* SOURCE_ADIOS2_CORE_ATTRIBUTE_H_ */
diff --git a/source/adios2/core/Attribute.tcc b/source/adios2/core/Attribute.tcc
new file mode 100644
index 000000000..47343256f
--- /dev/null
+++ b/source/adios2/core/Attribute.tcc
@@ -0,0 +1,41 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Attribute.tcc
+ *
+ *  Created on: Aug 1, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_ATTRIBUTE_TCC_
+#define ADIOS2_CORE_ATTRIBUTE_TCC_
+
+#include "Attribute.h"
+
+#include "adios2/ADIOSMacros.h"
+#include "adios2/helper/adiosFunctions.h" //GetType<T>
+
+namespace adios2
+{
+
+#define declare_type(T)                                                        \
+                                                                               \
+    template <>                                                                \
+    Attribute<T>::Attribute(const std::string &name, const T *array,           \
+                            const size_t elements)                             \
+    : AttributeBase(name, GetType<T>(), elements), m_DataArray(array),         \
+      m_DataValue()                                                            \
+    {                                                                          \
+    }                                                                          \
+                                                                               \
+    template <>                                                                \
+    Attribute<T>::Attribute(const std::string &name, const T &value)           \
+    : AttributeBase(name, GetType<T>(), 1), m_DataValue()                      \
+    {                                                                          \
+    }
+
+ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_type)
+#undef declare_type
+
+} // end namespace adios2
diff --git a/source/adios2/core/AttributeBase.cpp b/source/adios2/core/AttributeBase.cpp
new file mode 100644
index 000000000..498e7fbfc
--- /dev/null
+++ b/source/adios2/core/AttributeBase.cpp
@@ -0,0 +1,22 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * AttributeBase.cpp
+ *
+ *  Created on: Aug 1, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "AttributeBase.h"
+
+namespace adios2
+{
+
+AttributeBase::AttributeBase(const std::string &name, const std::string type,
+                             const size_t elements)
+: m_Name(name), m_Type(type), m_Elements(elements)
+{
+}
+
+} // end namespace adios2
diff --git a/source/adios2/core/AttributeBase.h b/source/adios2/core/AttributeBase.h
new file mode 100644
index 000000000..cf09b54f3
--- /dev/null
+++ b/source/adios2/core/AttributeBase.h
@@ -0,0 +1,39 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * AttributeBase.h : base class for Attribute<T> class, allows RTTI at read time
+ *
+ *  Created on: Aug 1, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_ATTRIBUTEBASE_H_
+#define ADIOS2_CORE_ATTRIBUTEBASE_H_
+
+namespace adios2
+{
+
+class AttributeBase
+{
+
+public:
+    const std::string m_Name;
+    const std::string m_Type;
+    const size_t m_Elements;
+
+    /**
+     * Unique constructor used by Attribute<T> derived class
+     * @param name
+     * @param type
+     * @param elements
+     */
+    AttributeBase(const std::string &name, const std::string type,
+                  const size_t elements);
+
+    virtual ~AttributeBase() = default;
+};
+
+} // end namespace adios2
+
+#endif /* ADIOS2_CORE_ATTRIBUTEBASE_H_ */
diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp
index fe70d534e..4fd7b69fc 100644
--- a/source/adios2/core/IO.cpp
+++ b/source/adios2/core/IO.cpp
@@ -62,7 +62,7 @@ unsigned int IO::AddTransport(const std::string type, const Params &parameters)
 
 VariableCompound &IO::GetVariableCompound(const std::string &name)
 {
-    return m_Compound.at(GetVariableIndex(name));
+    return m_Compound.at(GetMapIndex(name, m_Variables, "VariableCompound"));
 }
 
 std::string IO::GetVariableType(const std::string &name) const
@@ -235,30 +235,42 @@ std::shared_ptr<Engine> IO::Open(const std::string &name,
 }
 
 // PRIVATE Functions
-unsigned int IO::GetVariableIndex(const std::string &name) const
+unsigned int IO::GetMapIndex(const std::string &name, const DataMap &dataMap,
+                             const std::string hint) const
 {
+    auto itDataMap = dataMap.find(name);
+
     if (m_DebugMode)
     {
-        if (!VariableExists(name))
+        if (IsEnd(itDataMap, dataMap))
         {
-            throw std::invalid_argument(
-                "ERROR: variable " + m_Name +
-                " wasn't created with DefineVariable, in call to IO object " +
-                m_Name + " GetVariable\n");
+            throw std::invalid_argument("ERROR: " + hint + " " + m_Name +
+                                        " wasn't created with Define " + hint +
+                                        ", in call to IO object " + m_Name +
+                                        " Get" + hint + "\n");
         }
     }
-    auto itVariable = m_Variables.find(name);
-    return itVariable->second.second;
+    return itDataMap->second.second;
+}
+
+void IO::CheckAttributeCommon(const std::string &name) const
+{
+    auto itAttribute = m_Attributes.find(name);
+    if (!IsEnd(itAttribute, m_Attributes))
+    {
+        throw std::invalid_argument("ERROR: attribute " + name +
+                                    " exists in IO object " + m_Name +
+                                    ", in call to DefineAttribute\n");
+    }
 }
 
-bool IO::VariableExists(const std::string &name) const
+bool IO::IsEnd(DataMap::const_iterator itDataMap, const DataMap &dataMap) const
 {
-    bool exists = false;
-    if (m_Variables.count(name) == 1)
+    if (itDataMap == dataMap.end())
     {
-        exists = true;
+        return true;
     }
-    return exists;
+    return false;
 }
 
 void IO::CheckTransportType(const std::string type) const
diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h
index 59fc9f6c7..a738fd7bc 100644
--- a/source/adios2/core/IO.h
+++ b/source/adios2/core/IO.h
@@ -24,12 +24,16 @@
 #include "adios2/ADIOSMPICommOnly.h"
 #include "adios2/ADIOSMacros.h"
 #include "adios2/ADIOSTypes.h"
+#include "adios2/core/Attribute.h"
 #include "adios2/core/Variable.h"
 #include "adios2/core/VariableCompound.h"
 
 namespace adios2
 {
 
+/** used for Variables and Attributes */
+using DataMap = std::map<std::string, std::pair<std::string, unsigned int>>;
+
 // forward declaration needed as IO is passed to Engine derived
 // classes
 class Engine;
@@ -137,6 +141,26 @@ public:
                            const Dims start = Dims{}, const Dims count = Dims{},
                            const bool constantShape = false);
 
+    /**
+     * Define attribute from contiguous data array
+     * @param name must be unique for the IO object
+     * @param array pointer to user data
+     * @param elements number of data elements
+     * @return reference to internal Attribute
+     */
+    template <class T>
+    Attribute<T> &DefineAttribute(const std::string &name, const T *array,
+                                  const size_t elements);
+
+    /**
+     * Define attribute from a single variable
+     * @param name must be unique for the IO object
+     * @param value single data value
+     * @return reference to internal Attribute
+     */
+    template <class T>
+    Attribute<T> &DefineAttribute(const std::string &name, const T &value);
+
     /**
      * Removes an existing Variable previously created with DefineVariable or
      * DefineVariableCompound
@@ -163,6 +187,15 @@ public:
      */
     VariableCompound &GetVariableCompound(const std::string &name);
 
+    /**
+     * Gets an existing attribute of primitive type by name
+     * @param name of attribute to be retrieved
+     * @return reference to an existing attribute created with DefineAttribute
+     * throws an exception if Attribute is not found
+     */
+    template <class T>
+    Attribute<T> &GetAttribute(const std::string &name);
+
     /**
      * Get the type if variable (by name id) exists
      * @param name input id
@@ -222,7 +255,7 @@ private:
      *        pair.second = index in fixed size map (e.g. m_Int8, m_Double)
      * </pre>
      */
-    std::map<std::string, std::pair<std::string, unsigned int>> m_Variables;
+    DataMap m_Variables;
 
     /** Variable containers based on fixed-size type */
     std::map<unsigned int, Variable<char>> m_Char;
@@ -243,25 +276,63 @@ private:
     std::map<unsigned int, Variable<cldouble>> m_CLDouble;
     std::map<unsigned int, VariableCompound> m_Compound;
 
-    std::map<std::string, std::string> m_AttributesString;
-    std::map<std::string, double> m_AttributesNumeric;
-
-    std::set<std::string> m_EngineNames;
-
     /** Gets the internal reference to a variable map for type T
      *  This function is specialized in IO.tcc */
     template <class T>
     std::map<unsigned int, Variable<T>> &GetVariableMap();
 
-    /** Gets the internal index in variable map for an existing variable */
-    unsigned int GetVariableIndex(const std::string &name) const;
+    /**
+     * Map holding attribute identifiers
+     * <pre>
+     * key: unique attribute name,
+     * value: pair.first = type as string GetType<T> from
+     *                     helper/adiosTemplates.h
+     *        pair.second = index in fixed size map (e.g. m_Int8, m_Double)
+     * </pre>
+     */
+    DataMap m_Attributes;
+
+    std::map<unsigned int, Attribute<std::string>> m_StringA;
+    std::map<unsigned int, Attribute<char>> m_CharA;
+    std::map<unsigned int, Attribute<unsigned char>> m_UCharA;
+    std::map<unsigned int, Attribute<short>> m_ShortA;
+    std::map<unsigned int, Attribute<unsigned short>> m_UShortA;
+    std::map<unsigned int, Attribute<int>> m_IntA;
+    std::map<unsigned int, Attribute<unsigned int>> m_UIntA;
+    std::map<unsigned int, Attribute<long int>> m_LIntA;
+    std::map<unsigned int, Attribute<unsigned long int>> m_ULIntA;
+    std::map<unsigned int, Attribute<long long int>> m_LLIntA;
+    std::map<unsigned int, Attribute<unsigned long long int>> m_ULLIntA;
+    std::map<unsigned int, Attribute<float>> m_FloatA;
+    std::map<unsigned int, Attribute<double>> m_DoubleA;
+    std::map<unsigned int, Attribute<long double>> m_LDoubleA;
+
+    template <class T>
+    std::map<unsigned int, Attribute<T>> &GetAttributeMap();
 
     /**
-     * Checks if variable exists by checking its name
-     * @param name unique variable name to be checked against existing variables
-     * @return true: variable name exists, false: variable name doesn't exist
+     * Gets map index for Variables or Attributes
+     * @param name
+     * @param dataMap m_Variables or m_Attributes
+     * @param hint "Variable", "Attribute", or "VariableCompound"
+     * @return index in type map
      */
-    bool VariableExists(const std::string &name) const;
+    unsigned int GetMapIndex(const std::string &name, const DataMap &dataMap,
+                             const std::string hint) const;
+
+    /** Checks if attribute exists, called from DefineAttribute different
+     * signatures */
+    void CheckAttributeCommon(const std::string &name) const;
+
+    std::set<std::string> m_EngineNames;
+
+    /**
+     * Checks if iterator points to end. Used for Variables and Attributes.
+     * @param itDataMap iterator to be tested
+     * @param dataMap map
+     * @return true: itDataMap == dataMap.end(), false otherwise
+     */
+    bool IsEnd(DataMap::const_iterator itDataMap, const DataMap &dataMap) const;
 
     void CheckTransportType(const std::string type) const;
 };
@@ -276,6 +347,15 @@ private:
 ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
 #undef declare_template_instantiation
 
+#define declare_template_instantiation(T)                                      \
+    extern template Attribute<T> &IO::DefineAttribute<T>(                      \
+        const std::string &name, const T *array, const size_t elements);       \
+    extern template Attribute<T> &IO::DefineAttribute<T>(                      \
+        const std::string &name, const T &value);
+
+ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_template_instantiation)
+#undef declare_template_instantiation
+
 } // end namespace adios
 
 #include "adios2/core/IO.inl"
diff --git a/source/adios2/core/IO.inl b/source/adios2/core/IO.inl
index 6ef9299c0..9dd0f53f2 100644
--- a/source/adios2/core/IO.inl
+++ b/source/adios2/core/IO.inl
@@ -2,7 +2,8 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * IO.inl inline template functions implementation of IO class
+ * IO.inl inline template functions implementation of IO class. VariableCompound
+ * can take any type so must be inlined as type is not known a priori.
  *
  *  Created on: May 15, 2017
  *      Author: William F Godoy godoywf@ornl.gov
@@ -27,14 +28,16 @@ VariableCompound &IO::DefineVariableCompound(const std::string &name,
 {
     if (m_DebugMode)
     {
-        if (VariableExists(name))
+        auto itVariable = m_Variables.find(name);
+        if (!IsEnd(itVariable, m_Variables))
         {
-            throw std::invalid_argument("ERROR: variable " + name +
-                                        " exists in IO object " + m_Name +
-                                        ", in call to DefineVariable\n");
+            throw std::invalid_argument(
+                "ERROR: compound variable " + name + " exists in IO object " +
+                m_Name + ", in call to DefineVariableCompound\n");
         }
     }
-    const unsigned int size = m_Compound.size();
+    const unsigned int size =
+        static_cast<const unsigned int>(m_Compound.size());
     auto itVariableCompound = m_Compound.emplace(
         size, VariableCompound(name, sizeof(T), shape, start, count,
                                constantShape, m_DebugMode));
@@ -42,6 +45,6 @@ VariableCompound &IO::DefineVariableCompound(const std::string &name,
     return itVariableCompound.first->second;
 }
 
-} // end namespace adios
+} // end namespace adios2
 
 #endif /* ADIOS2_CORE_IO_INL_ */
diff --git a/source/adios2/core/IO.tcc b/source/adios2/core/IO.tcc
index dddb31678..572fa53bf 100644
--- a/source/adios2/core/IO.tcc
+++ b/source/adios2/core/IO.tcc
@@ -32,7 +32,8 @@ Variable<T> &IO::DefineVariable(const std::string &name, const Dims shape,
 {
     if (m_DebugMode)
     {
-        if (VariableExists(name))
+        auto itVariable = m_Variables.find(name);
+        if (!IsEnd(itVariable, m_Variables))
         {
             throw std::invalid_argument("ERROR: variable " + name +
                                         " exists in IO object " + m_Name +
@@ -41,7 +42,8 @@ Variable<T> &IO::DefineVariable(const std::string &name, const Dims shape,
     }
 
     auto &variableMap = GetVariableMap<T>();
-    const unsigned int size = variableMap.size();
+    const unsigned int size =
+        static_cast<const unsigned int>(variableMap.size());
     auto itVariablePair =
         variableMap.emplace(size, Variable<T>(name, shape, start, count,
                                               constantShape, m_DebugMode));
@@ -53,7 +55,53 @@ Variable<T> &IO::DefineVariable(const std::string &name, const Dims shape,
 template <class T>
 Variable<T> &IO::GetVariable(const std::string &name)
 {
-    return GetVariableMap<T>().at(GetVariableIndex(name));
+    return GetVariableMap<T>().at(GetMapIndex(name, m_Variables, "Variable"));
+}
+
+template <class T>
+Attribute<T> &IO::DefineAttribute(const std::string &name, const T &value)
+{
+    if (m_DebugMode)
+    {
+        CheckAttributeCommon(name);
+    }
+
+    auto &attributeMap = GetAttributeMap<T>();
+    const unsigned int size =
+        static_cast<const unsigned int>(attributeMap.size());
+
+    auto itAttributePair =
+        attributeMap.emplace(size, Attribute<T>(name, value));
+    m_Attributes.emplace(name, std::make_pair(GetType<T>(), size));
+
+    return itAttributePair.first->second;
+}
+
+template <class T>
+Attribute<T> &IO::DefineAttribute(const std::string &name, const T *array,
+                                  const size_t elements)
+{
+    if (m_DebugMode)
+    {
+        CheckAttributeCommon(name);
+    }
+
+    auto &attributeMap = GetAttributeMap<T>();
+    const unsigned int size =
+        static_cast<const unsigned int>(attributeMap.size());
+
+    auto itAttributePair =
+        attributeMap.emplace(size, Attribute<T>(name, array, elements));
+    m_Attributes.emplace(name, std::make_pair(GetType<T>(), size));
+
+    return itAttributePair.first->second;
+}
+
+template <class T>
+Attribute<T> &IO::GetAttribute(const std::string &name)
+{
+    return GetAttributeMap<T>().at(
+        GetMapIndex(name, m_Attributes, "Attribute"));
 }
 
 // PRIVATE
@@ -153,6 +201,91 @@ std::map<unsigned int, Variable<cldouble>> &IO::GetVariableMap()
     return m_CLDouble;
 }
 
-} // end namespace adios
+// attributes
+template <>
+std::map<unsigned int, Attribute<std::string>> &IO::GetAttributeMap()
+{
+    return m_StringA;
+}
+
+template <>
+std::map<unsigned int, Attribute<char>> &IO::GetAttributeMap()
+{
+    return m_CharA;
+}
+
+template <>
+std::map<unsigned int, Attribute<unsigned char>> &IO::GetAttributeMap()
+{
+    return m_UCharA;
+}
+
+template <>
+std::map<unsigned int, Attribute<short>> &IO::GetAttributeMap()
+{
+    return m_ShortA;
+}
+
+template <>
+std::map<unsigned int, Attribute<unsigned short>> &IO::GetAttributeMap()
+{
+    return m_UShortA;
+}
+
+template <>
+std::map<unsigned int, Attribute<int>> &IO::GetAttributeMap()
+{
+    return m_IntA;
+}
+
+template <>
+std::map<unsigned int, Attribute<unsigned int>> &IO::GetAttributeMap()
+{
+    return m_UIntA;
+}
+
+template <>
+std::map<unsigned int, Attribute<long int>> &IO::GetAttributeMap()
+{
+    return m_LIntA;
+}
+
+template <>
+std::map<unsigned int, Attribute<unsigned long int>> &IO::GetAttributeMap()
+{
+    return m_ULIntA;
+}
+
+template <>
+std::map<unsigned int, Attribute<long long int>> &IO::GetAttributeMap()
+{
+    return m_LLIntA;
+}
+
+template <>
+std::map<unsigned int, Attribute<unsigned long long int>> &IO::GetAttributeMap()
+{
+    return m_ULLIntA;
+}
+
+template <>
+std::map<unsigned int, Attribute<float>> &IO::GetAttributeMap()
+{
+    return m_FloatA;
+}
+
+template <>
+std::map<unsigned int, Attribute<double>> &IO::GetAttributeMap()
+{
+    return m_DoubleA;
+}
+
+template <>
+std::map<unsigned int, Attribute<long double>> &IO::GetAttributeMap()
+{
+    return m_LDoubleA;
+}
+
+} // end namespace adios2
 
 #endif /* ADIOS2_CORE_IO_TCC_ */
diff --git a/source/adios2/core/Variable.h b/source/adios2/core/Variable.h
index 9ed428735..8f5482857 100644
--- a/source/adios2/core/Variable.h
+++ b/source/adios2/core/Variable.h
@@ -54,7 +54,7 @@ public:
                 const Dims count, const bool constantShape,
                 const bool debugMode);
 
-    virtual ~Variable<T>() = default;
+    ~Variable<T>() = default;
 
     void ApplyTransforms() final;
 };
diff --git a/source/adios2/core/Variable.tcc b/source/adios2/core/Variable.tcc
index e5a241109..603b9300d 100644
--- a/source/adios2/core/Variable.tcc
+++ b/source/adios2/core/Variable.tcc
@@ -14,7 +14,7 @@
 #include "Variable.h"
 
 #include "adios2/ADIOSMacros.h"
-#include "adios2/helper/adiosFunctions.h" //GetType
+#include "adios2/helper/adiosFunctions.h" //GetType<T>
 
 namespace adios2
 {
-- 
GitLab