diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/Query.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/Query.h
index f3cde970c7cb54bec945d5a7bb6abd64deea6713..60dfaf7f39223a3b6b9b11caa5c33caffa963f26 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/Query.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/Query.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef GEOMODELKERNEL_QUERY_H
@@ -18,54 +18,31 @@
  * based on Barton & Nackman's "Scientific and Engineering C++"              
  */
 
-#include <stdexcept>
-template < class T > class Query
+#include <GeoModelKernel/throwExcept.h>
+#include <optional>
+template < class T > class Query: public std::optional<T>
 {
 
 public:
-
-  // Constructor: 
-  inline Query (const T &);
-
-  // Default constructor: 
-  inline Query ();
+  /// Use all constructors from the std::optional
+  using std::optional<T>::optional;
 
   // Convert to "T"  
-  inline operator         T () const;
+  inline operator T () const;
 
   // Test Validity 
   inline bool isValid () const;
 
-private:
-
-  bool m_failed;
-  T m_instance;
-
 };
 
-
-template < class T > inline Query < T >::Query (const T & t):
-m_failed (false),
-m_instance (t)
-{
-}
-
-template < class T > inline Query < T >::Query ():
-m_failed (true),
-m_instance (T())
-{
+template < class T > inline Query < T >::operator T () const {
+  if (!this->isValid()){
+    THROW_EXCEPTION("Nothing has been saved in query of type "<<typeid(T).name());
+  }
+  return this->value_or(T{});
 }
-
-template < class T > inline Query < T >::operator         T () const
-{
-  if (m_failed)
-    throw std::range_error ("Failed query");
-  return m_instance;
-}
-
-template < class T > inline bool Query < T >::isValid () const
-{
-  return !m_failed;
+template < class T > inline bool Query < T >::isValid () const {
+  return this->has_value();
 }
 
 
diff --git a/GeoModelCore/GeoModelKernel/tests/testQuery.cxx b/GeoModelCore/GeoModelKernel/tests/testQuery.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..61cc302d89ef63f6d71af684f78141c09f4c1c12
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/tests/testQuery.cxx
@@ -0,0 +1,78 @@
+/*
+  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
+ */
+#include "GeoModelKernel/Query.h"
+#include "GeoModelKernel/throwExcept.h"
+
+#include <stdlib.h>
+#include <iostream>
+
+
+#define RETURN_FAILURE(MSG) {                                     \
+    std::cerr<<__FILE__<<":"<<__LINE__<<" -- "<<MSG<<std::endl;   \
+    return EXIT_FAILURE;                                          \
+}
+int main() {
+
+    {
+        /// Test that the default constructor generates an invalid query
+        Query<int> emptyQuery{};
+        if (emptyQuery.isValid()){
+            RETURN_FAILURE("Empty query is not supposed to be valid." );
+        }
+    }
+    {
+        /// Test that the nullopt constructor does what it's supposed to do
+        Query<int>emptyQuery{std::nullopt};
+        if (emptyQuery.isValid()){
+            RETURN_FAILURE("std::nullopt query is not supposed to be valid." );
+        }
+    }
+
+    Query<int> initQuery{5};
+    if (!initQuery.isValid()){
+        RETURN_FAILURE("Query is supposed to be valid... And have value of 5." );
+    }
+    if (initQuery != 5) {
+        RETURN_FAILURE("Query is valid but has not 5 but instead "<<initQuery);
+    }
+    if (initQuery != 5) {
+        RETURN_FAILURE("Query is valid but has not 5 but instead "<<initQuery);
+    }
+    Query<int> copyQuery{initQuery};
+    if (!copyQuery.isValid()){
+        RETURN_FAILURE("The copy query is constructed from another valid one but is invalid...");
+    }
+    if (copyQuery.value_or(-9999) != initQuery.value_or(9999)){
+        RETURN_FAILURE("The copy query stores "<<copyQuery<<" while the other one has "<<initQuery);
+    }
+    copyQuery = std::nullopt;
+    if (copyQuery.isValid()){
+        RETURN_FAILURE("After setting back to nullopt it's supposed to be invalid." );
+    }
+    copyQuery = 7;
+    if (!copyQuery.isValid()){
+        RETURN_FAILURE("Expect the query to be valid." );
+    }
+    if (copyQuery != 7) {
+        RETURN_FAILURE("Expect the query to be 7 and not "<<copyQuery); 
+    }
+    copyQuery = std::move(initQuery);
+    if (copyQuery != 5) {
+        RETURN_FAILURE("Expect the query to be 5 and not "<<copyQuery); 
+    }
+    /// Apparently, the move on an optional does not invalidate the optional (https://stackoverflow.com/questions/51805059/why-does-moving-stdoptional-not-reset-state)
+    ///if (initQuery.isValid()) {
+    ///    RETURN_FAILURE("Initial query needs to be invalid and not "<<initQuery); 
+    ///}
+    initQuery = copyQuery;
+    if (!initQuery.isValid()) {
+        RETURN_FAILURE("Initial query needs to be valid again"); 
+    }
+    if (copyQuery.value_or(-9999) != initQuery.value_or(9999)){
+        RETURN_FAILURE("The copy query stores "<<copyQuery<<" while the other one has "<<initQuery);
+    }
+    std::cout<<__FILE__<<": - Test is passed. "<<std::endl;
+    return EXIT_SUCCESS;
+}
+