diff --git a/src/TNL/Containers/DistributedVector.h b/src/TNL/Containers/DistributedVector.h
index db4e46e68616244399e85fa7903ebe53a1e30585..be9ff657f1cd3c8ad49bf6af8a0aa09fc9242c6a 100644
--- a/src/TNL/Containers/DistributedVector.h
+++ b/src/TNL/Containers/DistributedVector.h
@@ -134,8 +134,15 @@ public:
    void scan( IndexType begin = 0, IndexType end = 0 );
 };
 
+// Enable expression templates for DistributedVector
+namespace Expressions {
+   template< typename Real, typename Device, typename Index, typename Communicator >
+   struct HasEnabledDistributedExpressionTemplates< DistributedVector< Real, Device, Index, Communicator > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/DistributedVector.hpp>
-#include <TNL/Containers/DistributedVectorExpressions.h>
diff --git a/src/TNL/Containers/DistributedVectorExpressions.h b/src/TNL/Containers/DistributedVectorExpressions.h
deleted file mode 100644
index 0d6d73e670eb2c745d6b4158da8cb8ec1ab165a7..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/DistributedVectorExpressions.h
+++ /dev/null
@@ -1,936 +0,0 @@
-/***************************************************************************
-                          DistributedVectorExpressions.h  -  description
-                             -------------------
-    begin                : Jul 1, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-#ifndef DOXYGEN_ONLY
-
-#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h>
-
-#include "DistributedVector.h"
-
-namespace TNL {
-namespace Containers {
-
-////
-// Addition
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Addition >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator+( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator+( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator+( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-////
-// Subtraction
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Subtraction >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-////
-// Multiplication
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Multiplication >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator*( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator*( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator*( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-////
-// Division
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Division >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator/( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator/( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator/( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-////
-// Comparison operations - operator ==
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::EQ( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator==( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator==( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator==( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-////
-// Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::NE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator!=( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator!=( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator!=( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-////
-// Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-////
-// Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Minus
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Expressions::Minus >( a );
-}
-
-////
-// Scalar product
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-Real
-operator,( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-Real
-operator,( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator,( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator,( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator,( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-} //namespace Containers
-
-////
-// All functions are supposed to be in namespace TNL
-
-////
-// Min
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Min >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-min( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-min( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-min( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Max
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Max >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-max( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-max( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-max( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-dot( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-dot( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-dot( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-
-////
-// Abs
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-abs( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-////
-// Power
-template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType >
-auto
-pow( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ExpType& exp )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ExpType, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-exp( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sqrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cbrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log10( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log2( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sine
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cosine
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tangent
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-tan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-asin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-acos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-atan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sinh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cosh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-tanh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-asinh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-acosh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-atanh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-floor( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-ceil( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sign( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType, typename Real, typename Device, typename Index, typename Communicator,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-Real
-min( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionMin( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-std::pair< Index, std::decay_t< Real > >
-argMin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionArgMin( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-Real
-max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionMax( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-std::pair< Index, std::decay_t< Real > >
-argMax( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionArgMax( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-sum( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionSum( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-maxNorm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-l1Norm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionL1Norm( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-l2Norm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return TNL::sqrt( Containers::Expressions::DistributedExpressionL2Norm( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator,
-          typename Real2 >
-auto
-lpNorm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::DistributedExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-product( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionProduct( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-logicalOr( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionLogicalOr( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-binaryOr( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionBinaryOr( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-logicalAnd( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionLogicalAnd( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-binaryAnd( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionBinaryAnd( a );
-}
-
-} // namespace TNL
-#endif // DOXYGEN_ONLY
diff --git a/src/TNL/Containers/DistributedVectorView.h b/src/TNL/Containers/DistributedVectorView.h
index 70452c50d17b8a08004a3ad162005154eb228ba8..72bc7588120d0527f6d4505a231fe37b33ba2dce 100644
--- a/src/TNL/Containers/DistributedVectorView.h
+++ b/src/TNL/Containers/DistributedVectorView.h
@@ -13,6 +13,7 @@
 #pragma once
 
 #include <TNL/Containers/DistributedArrayView.h>
+#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h>
 #include <TNL/Containers/VectorView.h>
 
 namespace TNL {
@@ -137,8 +138,15 @@ public:
    void scan( IndexType begin = 0, IndexType end = 0 );
 };
 
+// Enable expression templates for DistributedVector
+namespace Expressions {
+   template< typename Real, typename Device, typename Index, typename Communicator >
+   struct HasEnabledDistributedExpressionTemplates< DistributedVectorView< Real, Device, Index, Communicator > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/DistributedVectorView.hpp>
-#include <TNL/Containers/DistributedVectorViewExpressions.h>
diff --git a/src/TNL/Containers/DistributedVectorViewExpressions.h b/src/TNL/Containers/DistributedVectorViewExpressions.h
deleted file mode 100644
index 27936df1021412705a0728c38e0ed2b82b73231b..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/DistributedVectorViewExpressions.h
+++ /dev/null
@@ -1,718 +0,0 @@
-/***************************************************************************
-                          DistributedVectorViewExpressions.h  -  description
-                             -------------------
-    begin                : Jun 28, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-#ifndef DOXYGEN_ONLY
-
-#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h>
-#include <TNL/Exceptions/NotImplementedError.h>
-
-#include "DistributedVectorView.h"
-
-namespace TNL {
-namespace Containers {
-
-////
-// Addition
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Addition >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator+( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-////
-// Subtraction
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Subtraction >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-////
-// Multiplication
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Multiplication >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator*( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-////
-// Division
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Division >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator/( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-////
-// Comparison operations - operator ==
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::EQ( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator==( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-////
-// Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::NE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator!=( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-////
-// Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-////
-// Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Minus
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Expressions::Minus >( a );
-}
-
-////
-// Scalar product
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator,( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator,( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator,( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-} // namespace Containers
-
-////
-// All functions are supposed to be in namespace TNL
-
-////
-// Min
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Min >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-min( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Max
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Max >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-max( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2, typename Communicator >
-auto
-dot( const Containers::DistributedVectorView< Real1, Device, Index1, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index2, Communicator >& b )
-{
-   return (a, b);
-}
-
-////
-// Abs
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-abs( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-
-////
-// Power
-template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType >
-auto
-pow( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ExpType& exp )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< Containers::DistributedVectorView< Real, Device, Index, Communicator >, ExpType, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-exp( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sqrt( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cbrt( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log10( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log2( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sine
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cosine
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tangent
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-tan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-asin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-acos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-atan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sinh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cosh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-tanh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-asinh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-acosh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-atanh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-floor( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-ceil( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sign( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType, typename Real, typename Device, typename Index, typename Communicator,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename Real, typename Device, typename Index, typename Communicator >
-Real
-min( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionMin( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-std::pair< Index, std::decay_t< Real > >
-argMin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionArgMin( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-Real
-max( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionMax( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-std::pair< Index, std::decay_t< Real > >
-argMax( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionArgMax( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sum( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionSum( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-maxNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-l1Norm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionL1Norm( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-l2Norm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return TNL::sqrt( Containers::Expressions::DistributedExpressionL2Norm( a ) );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator, typename Real2 >
-auto
-lpNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::DistributedExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-product( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionProduct( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-logicalOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionLogicalOr( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-binaryOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionBinaryOr( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-logicalAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionLogicalAnd( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-binaryAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionBinaryAnd( a );
-}
-
-} // namespace TNL
-#endif // DOXYGEN_ONLY
diff --git a/src/TNL/Containers/Expressions/Comparison.h b/src/TNL/Containers/Expressions/Comparison.h
index 98e39ad8c561240f2ac0522844dd362059ebf710..40b823a1840e6b5d5458f18bbf3e2e9341b2403c 100644
--- a/src/TNL/Containers/Expressions/Comparison.h
+++ b/src/TNL/Containers/Expressions/Comparison.h
@@ -25,13 +25,14 @@ namespace Expressions {
 // Non-static comparison
 template< typename T1,
           typename T2,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
 struct Comparison;
 
 template< typename T1,
           typename T2,
-          bool BothAreVectors = IsArrayType< T1 >::value && IsArrayType< T2 >::value >
+          bool BothAreNonstaticVectors = IsArrayType< T1 >::value && IsArrayType< T2 >::value &&
+                                       ! IsStaticArrayType< T1 >::value && ! IsStaticArrayType< T2 >::value >
 struct VectorComparison;
 
 // If both operands are vectors we compare them using array operations.
@@ -64,7 +65,9 @@ struct VectorComparison< T1, T2, false >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] == b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] == view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 };
@@ -94,7 +97,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] > b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] > view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -107,7 +112,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] >= b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] >= view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -120,7 +127,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] < b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] < view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -133,7 +142,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] <= b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] <= view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 };
@@ -149,7 +160,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a == b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a == view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -163,7 +175,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a > b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a > view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -172,7 +185,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a >= b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a >= view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -181,7 +195,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a < b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a < view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -190,7 +205,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a <= b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a <= view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 };
@@ -206,7 +222,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] == b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] == b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -220,7 +237,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] > b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] > b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -229,7 +247,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] >= b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] >= b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -238,7 +257,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] < b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] < b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -247,7 +267,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] <= b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] <= b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 };
diff --git a/src/TNL/Containers/Expressions/DistributedComparison.h b/src/TNL/Containers/Expressions/DistributedComparison.h
index b5e0e96a9d756f55edb7bf15652ad1d0d34bc5d6..4cecc92bb9b3823db92df893c289c0233d26bb14 100644
--- a/src/TNL/Containers/Expressions/DistributedComparison.h
+++ b/src/TNL/Containers/Expressions/DistributedComparison.h
@@ -21,8 +21,8 @@ namespace Expressions {
 // Non-static comparison
 template< typename T1,
           typename T2,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
 struct DistributedComparison;
 
 /////
diff --git a/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h b/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h
index 355689039884e8e05caff040e232ffbcf26119ba..27c92e0e92cdaf2338cf62d15d266d096fede6b0 100644
--- a/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h
+++ b/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h
@@ -22,15 +22,12 @@ namespace Expressions {
 ////
 // Distributed unary expression template
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value >
-struct DistributedUnaryExpressionTemplate
-{};
+          template< typename > class Operation >
+struct DistributedUnaryExpressionTemplate;
 
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type >
-struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation, T1Type > >
+          template< typename > class Operation >
+struct HasEnabledDistributedExpressionTemplates< DistributedUnaryExpressionTemplate< T1, Operation > >
 : std::true_type
 {};
 
@@ -39,8 +36,8 @@ struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation,
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
 struct DistributedBinaryExpressionTemplate
 {};
 
@@ -49,7 +46,7 @@ template< typename T1,
           template< typename, typename > class Operation,
           ExpressionVariableType T1Type,
           ExpressionVariableType T2Type >
-struct IsExpressionTemplate< DistributedBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
+struct HasEnabledDistributedExpressionTemplates< DistributedBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
 : std::true_type
 {};
 
@@ -234,7 +231,7 @@ protected:
 // Distributed unary expression template
 template< typename T1,
           template< typename > class Operation >
-struct DistributedUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
+struct DistributedUnaryExpressionTemplate
 {
    using RealType = decltype( Operation< typename T1::RealType >::
                               evaluate( std::declval<T1>()[0] ) );
@@ -284,1909 +281,649 @@ protected:
    const T1& operand;
 };
 
+#ifndef DOXYGEN_ONLY
+
 ////
-// Output stream
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression )
+// Binary expressions addition
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+auto
+operator+( const ET1& a, const ET2& b )
 {
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression.getElement( i ) << ", ";
-   str << expression.getElement( expression.getSize() - 1 ) << " ]";
-   return str;
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Addition >( a, b );
 }
 
-template< typename T,
-          template< typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const DistributedUnaryExpressionTemplate< T, Operation >& expression )
+////
+// Binary expression subtraction
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+auto
+operator-( const ET1& a, const ET2& b )
 {
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression.getElement( i ) << ", ";
-   str << expression.getElement( expression.getSize() - 1 ) << " ]";
-   return str;
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b );
 }
 
 ////
-// Operators are supposed to be in the same namespace as the expression templates
-
-#ifndef DOXYGEN_ONLY
-
-////
-// Binary expressions addition
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Binary expression multiplication
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator*( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression division
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator+( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator/( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Division >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-operator+( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+////
+// Comparison operator ==
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator==( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::EQ( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-auto
-operator+( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+////
+// Comparison operator !=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator!=( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::NE( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-auto
-operator+( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+////
+// Comparison operator <
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator<( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::LT( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator+( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+////
+// Comparison operator <=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator<=( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::LE( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Comparison operator >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator>( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::GT( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator+( const DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Comparison operator >=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator>=( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::GE( a, b );
 }
 
 ////
-// Binary expression subtraction
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Scalar product
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator,( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedExpressionSum( a * b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator-( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+dot( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return (a, b);
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Unary expression minus
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator-( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+operator-( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Minus >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Binary expression min
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator-( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+min( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Min >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Binary expression max
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator-( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+max( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Max >( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Abs
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator-( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+abs( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Abs >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Pow
+template< typename ET1, typename Real,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+pow( const ET1& a, const Real& exp )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, Real, Pow >( a, exp );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Exp
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator-( const DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+exp( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Exp >( a );
 }
 
 ////
-// Binary expression multiplication
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Sqrt
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+sqrt( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Sqrt >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Cbrt
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+cbrt( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Cbrt >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Log
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+log( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Log >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Log10
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+log10( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Log10 >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Log2
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+log2( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Log2 >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Sin
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+sin( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Sin >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Cos
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
+cos( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Cos >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Tan
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+tan( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Tan >( a );
 }
 
 ////
-// Binary expression division
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Asin
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+asin( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Asin >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Acos
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+acos( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Acos >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Atan
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+atan( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Atan >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Sinh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+sinh( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Sinh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Cosh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+cosh( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Cosh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Tanh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+tanh( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Tanh >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Asinh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+asinh( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Asinh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Acosh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+acosh( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Acosh >( a );
 }
 
 ////
-// Comparison operator ==
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+// Atanh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+atanh( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Atanh >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator==( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+////
+// Floor
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+floor( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Floor >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator==( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-            const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+////
+// Ceil
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+ceil( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Ceil >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator==( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+////
+// Sign
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+sign( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Sign >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator==( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+////
+// Cast
+template< typename ResultType,
+          typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >,
+          // workaround: templated type alias cannot be declared at block level
+          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation,
+          typename = void, typename = void >
+auto
+cast( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, CastOperation >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator==( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+////
+// Vertical operations
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+min( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedExpressionMin( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+argMin( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedExpressionArgMin( a );
 }
 
-////
-// Comparison operator !=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+max( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionMax( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator!=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+argMax( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionArgMax( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+sum( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionSum( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator!=( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-            const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+maxNorm( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return max( abs( a ) );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator!=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+l1Norm( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return sum( abs( a ) );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator!=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+l2Norm( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   using TNL::sqrt;
+   return sqrt( sum( a * a ) );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename Real,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+lpNorm( const ET1& a, const Real& p )
+// since (1.0 / p) has type double, TNL::pow returns double
+-> double
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   if( p == 1.0 )
+      return l1Norm( a );
+   if( p == 2.0 )
+      return l2Norm( a );
+   using TNL::pow;
+   return pow( sum( pow( abs( a ), p ) ), 1.0 / p );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+product( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionProduct( a );
 }
 
-////
-// Comparison operator <
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+logicalOr( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionLogicalOr( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+logicalAnd( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionLogicalAnd( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+binaryOr( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionBinaryOr( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+binaryAnd( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionBinaryAnd( a );
 }
 
+////
+// Output stream
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-bool
-operator<( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+std::ostream& operator<<( std::ostream& str, const DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression.getElement( i ) << ", ";
+   str << expression.getElement( expression.getSize() - 1 ) << " ]";
+   return str;
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-////
-// Comparison operator <=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<=( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-            const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operator >
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operator >=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>=( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-            const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
+template< typename T,
           template< typename > class Operation >
-bool
-operator>=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Unary operations
-
-////
-// Minus
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-operator-( const DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-////
-// Scalar product
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator,( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return DistributedExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator,( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedExpressionSum( a * b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+std::ostream& operator<<( std::ostream& str, const DistributedUnaryExpressionTemplate< T, Operation >& expression )
 {
-   return DistributedExpressionSum( a * b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression.getElement( i ) << ", ";
+   str << expression.getElement( expression.getSize() - 1 ) << " ]";
+   return str;
 }
 
 #endif // DOXYGEN_ONLY
 
 } // namespace Expressions
-} // namespace Containers
-
-////
-// All operations are supposed to be in namespace TNL
-
-#ifndef DOXYGEN_ONLY
-
-////
-// Binary expression min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-min( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-min( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-min( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-min( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-     const typename Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Binary expression max
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-max( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-max( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-max( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
 
-template< typename T1,
-          template< typename > class Operation >
-auto
-max( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
+// Make all operators visible in the TNL::Containers namespace to be considered
+// even for DistributedVector and DistributedVectorView
+using Expressions::operator+;
+using Expressions::operator-;
+using Expressions::operator*;
+using Expressions::operator/;
+using Expressions::operator,;
+using Expressions::operator==;
+using Expressions::operator!=;
+using Expressions::operator<;
+using Expressions::operator<=;
+using Expressions::operator>;
+using Expressions::operator>=;
+
+// Make all functions visible in the TNL::Containers namespace
+using Expressions::dot;
+using Expressions::min;
+using Expressions::max;
+using Expressions::abs;
+using Expressions::pow;
+using Expressions::exp;
+using Expressions::sqrt;
+using Expressions::cbrt;
+using Expressions::log;
+using Expressions::log10;
+using Expressions::log2;
+using Expressions::sin;
+using Expressions::cos;
+using Expressions::tan;
+using Expressions::asin;
+using Expressions::acos;
+using Expressions::atan;
+using Expressions::sinh;
+using Expressions::cosh;
+using Expressions::tanh;
+using Expressions::asinh;
+using Expressions::acosh;
+using Expressions::atanh;
+using Expressions::floor;
+using Expressions::ceil;
+using Expressions::sign;
+using Expressions::cast;
+using Expressions::argMin;
+using Expressions::argMax;
+using Expressions::sum;
+using Expressions::maxNorm;
+using Expressions::l1Norm;
+using Expressions::l2Norm;
+using Expressions::lpNorm;
+using Expressions::product;
+using Expressions::logicalAnd;
+using Expressions::logicalOr;
+using Expressions::binaryAnd;
+using Expressions::binaryOr;
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Abs
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-abs( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-abs( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-////
-// Pow
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-auto
-pow( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-auto
-pow( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-exp( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-exp( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sqrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sqrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cbrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cbrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log10( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log10( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log2( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log2( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-tan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-tan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-asin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-asin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-acos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-acos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-atan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-atan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-tanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-tanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-asinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-asinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-acosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-acosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-atanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-atanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-floor( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-floor( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-ceil( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-ceil( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sign( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sign( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType,
-          typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-template< typename ResultType,
-          typename L1,
-          template< typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-argMin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionArgMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-argMin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionArgMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-argMax( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionArgMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-argMax( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionArgMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sum( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionSum( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sum( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionSum( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionL1Norm( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionL1Norm( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return TNL::sqrt( DistributedExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return TNL::sqrt( DistributedExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-auto
-lpNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( DistributedExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-auto
-lpNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( DistributedExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-product( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionProduct( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-product( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionProduct( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-logicalOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-logicalOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-logicalAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionLogicalAnd( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-logicalAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionLogicalAnd( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-binaryOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-binaryOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-binaryAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionBinaryAnd( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-binaryAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionBinaryAnd( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-#endif // DOXYGEN_ONLY
+} // namespace Containers
 
+// Make all functions visible in the main TNL namespace
+using Containers::dot;
+using Containers::min;
+using Containers::max;
+using Containers::abs;
+using Containers::pow;
+using Containers::exp;
+using Containers::sqrt;
+using Containers::cbrt;
+using Containers::log;
+using Containers::log10;
+using Containers::log2;
+using Containers::sin;
+using Containers::cos;
+using Containers::tan;
+using Containers::asin;
+using Containers::acos;
+using Containers::atan;
+using Containers::sinh;
+using Containers::cosh;
+using Containers::tanh;
+using Containers::asinh;
+using Containers::acosh;
+using Containers::atanh;
+using Containers::floor;
+using Containers::ceil;
+using Containers::sign;
+using Containers::cast;
+using Containers::argMin;
+using Containers::argMax;
+using Containers::sum;
+using Containers::maxNorm;
+using Containers::l1Norm;
+using Containers::l2Norm;
+using Containers::lpNorm;
+using Containers::product;
+using Containers::logicalAnd;
+using Containers::logicalOr;
+using Containers::binaryAnd;
+using Containers::binaryOr;
 
 ////
 // Evaluation with reduction
diff --git a/src/TNL/Containers/Expressions/DistributedVerticalOperations.h b/src/TNL/Containers/Expressions/DistributedVerticalOperations.h
index 43940417bb0aa7fa97afe17e4fee3e4ce703a819..178a5c03c50a36ff9c62e35e38a4a0aa68860532 100644
--- a/src/TNL/Containers/Expressions/DistributedVerticalOperations.h
+++ b/src/TNL/Containers/Expressions/DistributedVerticalOperations.h
@@ -148,51 +148,6 @@ auto DistributedExpressionSum( const Expression& expression ) -> std::decay_t< d
    return result;
 }
 
-template< typename Expression >
-auto DistributedExpressionL1Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) >
-{
-   using ResultType = std::decay_t< decltype( expression[0] ) >;
-   using IndexType = typename Expression::IndexType;
-   using CommunicatorType = typename Expression::CommunicatorType;
-
-   ResultType result = 0;
-   if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) {
-      const ResultType localResult = ExpressionL1Norm( expression.getConstLocalView() );
-      CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() );
-   }
-   return result;
-}
-
-template< typename Expression >
-auto DistributedExpressionL2Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) >
-{
-   using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >;
-   using IndexType = typename Expression::IndexType;
-   using CommunicatorType = typename Expression::CommunicatorType;
-
-   ResultType result = 0;
-   if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) {
-      const ResultType localResult = ExpressionL2Norm( expression.getConstLocalView() );
-      CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() );
-   }
-   return result;
-}
-
-template< typename Expression, typename Real >
-auto DistributedExpressionLpNorm( const Expression& expression, const Real& p ) -> std::decay_t< decltype( TNL::pow( expression[0], p ) ) >
-{
-   using ResultType = std::decay_t< decltype( TNL::pow( expression[0], p ) ) >;
-   using IndexType = typename Expression::IndexType;
-   using CommunicatorType = typename Expression::CommunicatorType;
-
-   ResultType result = 0;
-   if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) {
-      const ResultType localResult = ExpressionLpNorm( expression.getConstLocalView(), p );
-      CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() );
-   }
-   return result;
-}
-
 template< typename Expression >
 auto DistributedExpressionProduct( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) >
 {
diff --git a/src/TNL/Containers/Expressions/ExpressionTemplates.h b/src/TNL/Containers/Expressions/ExpressionTemplates.h
index a0980baf6cf8ee751444df7d27205dfa9260f593..0cbb69342cb035c26dd2e4fc2740ae3d568afbf5 100644
--- a/src/TNL/Containers/Expressions/ExpressionTemplates.h
+++ b/src/TNL/Containers/Expressions/ExpressionTemplates.h
@@ -24,40 +24,35 @@ namespace TNL {
 namespace Containers {
 namespace Expressions {
 
-////
-// Non-static unary expression template
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value >
-struct UnaryExpressionTemplate
-{};
+          template< typename > class Operation >
+struct UnaryExpressionTemplate;
 
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type >
-struct IsExpressionTemplate< UnaryExpressionTemplate< T1, Operation, T1Type > >
+          template< typename > class Operation >
+struct HasEnabledExpressionTemplates< UnaryExpressionTemplate< T1, Operation > >
 : std::true_type
 {};
 
-////
-// Non-static binary expression template
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
-struct BinaryExpressionTemplate
-{};
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
+struct BinaryExpressionTemplate;
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation,
           ExpressionVariableType T1Type,
           ExpressionVariableType T2Type >
-struct IsExpressionTemplate< BinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
+struct HasEnabledExpressionTemplates< BinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
 : std::true_type
 {};
 
+
+////
+// Non-static binary expression template
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
@@ -67,6 +62,7 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ve
                               evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
+   using ConstViewType = BinaryExpressionTemplate;
 
    static_assert( std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value,
                   "Attempt to mix operands which have different DeviceType." );
@@ -74,7 +70,7 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ve
                   "Attempt to mix static and non-static operands in binary expression templates." );
 
    BinaryExpressionTemplate( const T1& a, const T2& b )
-   : op1( a ), op2( b )
+   : op1( a.getConstView() ), op2( b.getConstView() )
    {
       TNL_ASSERT_EQ( op1.getSize(), op2.getSize(),
                      "Attempt to mix operands with different sizes." );
@@ -97,9 +93,14 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ve
       return op1.getSize();
    }
 
+   ConstViewType getConstView() const
+   {
+      return *this;
+   }
+
 protected:
-   const T1 op1;
-   const T2 op2;
+   const typename T1::ConstViewType op1;
+   const typename T2::ConstViewType op2;
 };
 
 template< typename T1,
@@ -111,9 +112,10 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ar
                               evaluate( std::declval<T1>()[0], std::declval<T2>() ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
+   using ConstViewType = BinaryExpressionTemplate;
 
    BinaryExpressionTemplate( const T1& a, const T2& b )
-   : op1( a ), op2( b ) {}
+   : op1( a.getConstView() ), op2( b ) {}
 
    RealType getElement( const IndexType i ) const
    {
@@ -132,8 +134,13 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ar
       return op1.getSize();
    }
 
+   ConstViewType getConstView() const
+   {
+      return *this;
+   }
+
 protected:
-   const T1 op1;
+   const typename T1::ConstViewType op1;
    const T2 op2;
 };
 
@@ -146,9 +153,10 @@ struct BinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorEx
                               evaluate( std::declval<T1>(), std::declval<T2>()[0] ) );
    using DeviceType = typename T2::DeviceType;
    using IndexType = typename T2::IndexType;
+   using ConstViewType = BinaryExpressionTemplate;
 
    BinaryExpressionTemplate( const T1& a, const T2& b )
-   : op1( a ), op2( b ) {}
+   : op1( a ), op2( b.getConstView() ) {}
 
    RealType getElement( const IndexType i ) const
    {
@@ -167,24 +175,30 @@ struct BinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorEx
       return op2.getSize();
    }
 
+   ConstViewType getConstView() const
+   {
+      return *this;
+   }
+
 protected:
    const T1 op1;
-   const T2 op2;
+   const typename T2::ConstViewType op2;
 };
 
 ////
 // Non-static unary expression template
 template< typename T1,
           template< typename > class Operation >
-struct UnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
+struct UnaryExpressionTemplate
 {
    using RealType = decltype( Operation< typename T1::RealType >::
                               evaluate( std::declval<T1>()[0] ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
+   using ConstViewType = UnaryExpressionTemplate;
 
    UnaryExpressionTemplate( const T1& a )
-   : operand( a ) {}
+   : operand( a.getConstView() ) {}
 
    RealType getElement( const IndexType i ) const
    {
@@ -203,1913 +217,658 @@ struct UnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
       return operand.getSize();
    }
 
+   ConstViewType getConstView() const
+   {
+      return *this;
+   }
+
 protected:
-   const T1 operand;
+   const typename T1::ConstViewType operand;
 };
 
+#ifndef DOXYGEN_ONLY
+
 ////
-// Output stream
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const BinaryExpressionTemplate< T1, T2, Operation >& expression )
+// Binary expressions addition
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+auto
+operator+( const ET1& a, const ET2& b )
 {
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression.getElement( i ) << ", ";
-   str << expression.getElement( expression.getSize() - 1 ) << " ]";
-   return str;
+   return BinaryExpressionTemplate< ET1, ET2, Addition >( a, b );
 }
 
-template< typename T,
-          template< typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const UnaryExpressionTemplate< T, Operation >& expression )
+////
+// Binary expression subtraction
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+auto
+operator-( const ET1& a, const ET2& b )
 {
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression.getElement( i ) << ", ";
-   str << expression.getElement( expression.getSize() - 1 ) << " ]";
-   return str;
+   return BinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b );
 }
 
 ////
-// Operators are supposed to be in the same namespace as the expression templates
-
-#ifndef DOXYGEN_ONLY
-
-////
-// Binary expressions addition
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Binary expression multiplication
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator+( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator*( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression division
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator+( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator/( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Division >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-operator+( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+////
+// Comparison operator ==
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator==( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::EQ( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-auto
-operator+( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+////
+// Comparison operator !=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator!=( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::NE( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-auto
-operator+( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+////
+// Comparison operator <
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator<( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::LT( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator+( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+////
+// Comparison operator <=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator<=( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::LE( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator+( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Comparison operator >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator>( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::GT( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator+( const UnaryExpressionTemplate< L1,LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Comparison operator >=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator>=( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::GE( a, b );
 }
 
 ////
-// Binary expression subtraction
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Scalar product
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator,( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return ExpressionSum( a * b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator-( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+dot( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return (a, b);
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Unary expression minus
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator-( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator-( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return UnaryExpressionTemplate< ET1, Minus >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Binary expression min
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator-( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+min( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Min >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Binary expression max
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator-( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+max( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Max >( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Abs
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator-( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+abs( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return UnaryExpressionTemplate< ET1, Abs >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Pow
+template< typename ET1, typename Real,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+pow( const ET1& a, const Real& exp )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return BinaryExpressionTemplate< ET1, Real, Pow >( a, exp );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Exp
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator-( const UnaryExpressionTemplate< L1,LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+exp( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return UnaryExpressionTemplate< ET1, Exp >( a );
 }
 
 ////
-// Binary expression multiplication
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Sqrt
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+sqrt( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Sqrt >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Cbrt
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+cbrt( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Cbrt >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Log
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+log( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Log >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Log10
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+log10( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Log10 >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Log2
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+log2( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Log2 >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Sin
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+sin( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Sin >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Cos
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1, ROperation >& b )
+cos( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Cos >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Tan
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const UnaryExpressionTemplate< L1,LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+tan( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Tan >( a );
 }
 
 ////
-// Binary expression division
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Asin
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+asin( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Asin >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Acos
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+acos( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Acos >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Atan
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+atan( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Atan >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Sinh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+sinh( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Sinh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Cosh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+cosh( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Cosh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Tanh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+tanh( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Tanh >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Asinh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+asinh( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Asinh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Acosh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const UnaryExpressionTemplate< L1,LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+acosh( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Acosh >( a );
 }
 
 ////
-// Comparison operator ==
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator==( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+// Atanh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+atanh( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Atanh >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator==( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+////
+// Floor
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+floor( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Floor >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator==( const UnaryExpressionTemplate< T1, Operation >& a,
-            const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+////
+// Ceil
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+ceil( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Ceil >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator==( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const BinaryExpressionTemplate< T1, T2, Operation >& b )
+////
+// Sign
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+sign( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Sign >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator==( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const UnaryExpressionTemplate< T1, Operation >& b )
+////
+// Cast
+template< typename ResultType,
+          typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >,
+          // workaround: templated type alias cannot be declared at block level
+          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation,
+          typename = void >
+auto
+cast( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, CastOperation >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator==( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+////
+// Vertical operations
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+min( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return ExpressionMin( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator==( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const UnaryExpressionTemplate< R1,ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+argMin( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return ExpressionArgMin( a );
 }
 
-////
-// Comparison operator !=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator!=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+max( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionMax( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator!=( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+argMax( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionArgMax( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator!=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const UnaryExpressionTemplate< R1, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+sum( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionSum( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator!=( const UnaryExpressionTemplate< T1, Operation >& a,
-            const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+maxNorm( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return max( abs( a ) );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator!=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const BinaryExpressionTemplate< T1, T2, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+l1Norm( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return sum( abs( a ) );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator!=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const UnaryExpressionTemplate< T1, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+l2Norm( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   using TNL::sqrt;
+   return sqrt( sum( a * a ) );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator!=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename Real,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+lpNorm( const ET1& a, const Real& p )
+// since (1.0 / p) has type double, TNL::pow returns double
+-> double
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   if( p == 1.0 )
+      return l1Norm( a );
+   if( p == 2.0 )
+      return l2Norm( a );
+   using TNL::pow;
+   return pow( sum( pow( abs( a ), p ) ), 1.0 / p );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator!=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const UnaryExpressionTemplate< R1,ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+product( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionProduct( a );
 }
 
-////
-// Comparison operator <
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+logicalAnd( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return ExpressionLogicalAnd( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const UnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-////
-// Comparison operator <=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<=( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const UnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<=( const UnaryExpressionTemplate< T1, Operation >& a,
-            const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operator >
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator>( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operator >=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>=( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>=( const UnaryExpressionTemplate< T1, Operation >& a,
-            const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator>=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Unary operations
-
-////
-// Minus
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return UnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-operator-( const UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return UnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-////
-// Scalar product
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator,( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return ExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator,( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const UnaryExpressionTemplate< R1, ROperation >& b )
+logicalOr( const ET1& a )
 {
-   return ExpressionSum( a * b );
+   return ExpressionLogicalOr( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator,( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+binaryAnd( const ET1& a )
 {
-   return ExpressionSum( a * b );
+   return ExpressionBinaryAnd( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator,( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+binaryOr( const ET1& a )
 {
-   return ExpressionSum( a * b );
+   return ExpressionBinaryOr( a );
 }
 
 #endif // DOXYGEN_ONLY
 
-} // namespace Expressions
-} // namespace Containers
-
-////
-// All operations are supposed to be in namespace TNL
-
-#ifndef DOXYGEN_ONLY
-
 ////
-// Binary expression min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-min( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
+// Output stream
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-auto
-min( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-min( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b )
+std::ostream& operator<<( std::ostream& str, const BinaryExpressionTemplate< T1, T2, Operation >& expression )
 {
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression.getElement( i ) << ", ";
+   str << expression.getElement( expression.getSize() - 1 ) << " ]";
+   return str;
 }
 
-template< typename T1,
+template< typename T,
           template< typename > class Operation >
-auto
-min( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-     const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-min( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+std::ostream& operator<<( std::ostream& str, const UnaryExpressionTemplate< T, Operation >& expression )
 {
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression.getElement( i ) << ", ";
+   str << expression.getElement( expression.getSize() - 1 ) << " ]";
+   return str;
 }
 
-////
-// Binary expression max
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
+} // namespace Expressions
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-max( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
+// Make all operators visible in the TNL::Containers namespace to be considered
+// even for Vector and VectorView
+using Expressions::operator+;
+using Expressions::operator-;
+using Expressions::operator*;
+using Expressions::operator/;
+using Expressions::operator,;
+using Expressions::operator==;
+using Expressions::operator!=;
+using Expressions::operator<;
+using Expressions::operator<=;
+using Expressions::operator>;
+using Expressions::operator>=;
+
+// Make all functions visible in the TNL::Containers namespace
+using Expressions::dot;
+using Expressions::min;
+using Expressions::max;
+using Expressions::abs;
+using Expressions::pow;
+using Expressions::exp;
+using Expressions::sqrt;
+using Expressions::cbrt;
+using Expressions::log;
+using Expressions::log10;
+using Expressions::log2;
+using Expressions::sin;
+using Expressions::cos;
+using Expressions::tan;
+using Expressions::asin;
+using Expressions::acos;
+using Expressions::atan;
+using Expressions::sinh;
+using Expressions::cosh;
+using Expressions::tanh;
+using Expressions::asinh;
+using Expressions::acosh;
+using Expressions::atanh;
+using Expressions::floor;
+using Expressions::ceil;
+using Expressions::sign;
+using Expressions::cast;
+using Expressions::argMin;
+using Expressions::argMax;
+using Expressions::sum;
+using Expressions::maxNorm;
+using Expressions::l1Norm;
+using Expressions::l2Norm;
+using Expressions::lpNorm;
+using Expressions::product;
+using Expressions::logicalAnd;
+using Expressions::logicalOr;
+using Expressions::binaryAnd;
+using Expressions::binaryOr;
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-max( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-max( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-max( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-max( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Abs
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-abs( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-abs( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-////
-// Pow
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-auto
-pow( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-auto
-pow( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-exp( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-exp( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sqrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sqrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cbrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cbrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log10( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log10( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log2( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log2( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-tan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-tan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-asin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-asin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-acos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-acos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-atan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-atan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sinh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sinh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cosh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cosh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-tanh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-tanh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-asinh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-asinh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-acosh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-acosh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-atanh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-atanh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-floor( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-floor( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-ceil( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-ceil( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sign( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sign( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType,
-          typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-template< typename ResultType,
-          typename L1,
-          template< typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-argMin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionArgMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-argMin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionArgMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-argMax( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionArgMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-argMax( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionArgMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sum( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionSum( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sum( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionSum( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionL1Norm( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionL1Norm( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return TNL::sqrt( ExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return TNL::sqrt( ExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-auto
-lpNorm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( ExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-auto
-lpNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( ExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-product( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionProduct( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-product( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionProduct( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-logicalOr( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-logicalOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-logicalAnd( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionLogicalAnd( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-logicalAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionLogicalAnd( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-binaryOr( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-binaryOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-binaryAnd( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionBinaryAnd( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-binaryAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionBinaryAnd( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-dot( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-dot( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-dot( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-dot( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-#endif // DOXYGEN_ONLY
+} // namespace Containers
 
+// Make all functions visible in the main TNL namespace
+using Containers::dot;
+using Containers::min;
+using Containers::max;
+using Containers::abs;
+using Containers::pow;
+using Containers::exp;
+using Containers::sqrt;
+using Containers::cbrt;
+using Containers::log;
+using Containers::log10;
+using Containers::log2;
+using Containers::sin;
+using Containers::cos;
+using Containers::tan;
+using Containers::asin;
+using Containers::acos;
+using Containers::atan;
+using Containers::sinh;
+using Containers::cosh;
+using Containers::tanh;
+using Containers::asinh;
+using Containers::acosh;
+using Containers::atanh;
+using Containers::floor;
+using Containers::ceil;
+using Containers::sign;
+using Containers::cast;
+using Containers::argMin;
+using Containers::argMax;
+using Containers::sum;
+using Containers::maxNorm;
+using Containers::l1Norm;
+using Containers::l2Norm;
+using Containers::lpNorm;
+using Containers::product;
+using Containers::logicalAnd;
+using Containers::logicalOr;
+using Containers::binaryAnd;
+using Containers::binaryOr;
 
 ////
 // Evaluation with reduction
diff --git a/src/TNL/Containers/Expressions/ExpressionVariableType.h b/src/TNL/Containers/Expressions/ExpressionVariableType.h
index ad9ab830ed30f1cbfc4f2701140ffb1efcb819e7..2095a4352c9874f6315f01dbaf475be2f1a66006 100644
--- a/src/TNL/Containers/Expressions/ExpressionVariableType.h
+++ b/src/TNL/Containers/Expressions/ExpressionVariableType.h
@@ -10,8 +10,7 @@
 
 #pragma once
 
-#include <TNL/TypeTraits.h>
-#include <TNL/Devices/Host.h>
+#include <TNL/Containers/Expressions/TypeTraits.h>
 
 namespace TNL {
 namespace Containers {
@@ -19,41 +18,24 @@ namespace Expressions {
 
 enum ExpressionVariableType { ArithmeticVariable, VectorExpressionVariable, OtherVariable };
 
-template< typename T,
-          bool IsArithmetic = std::is_arithmetic< T >::value,
-          bool IsVector = HasSubscriptOperator< T >::value >
-struct ExpressionVariableTypeGetter
+template< typename T, typename V = T >
+constexpr ExpressionVariableType
+getExpressionVariableType()
 {
-   static constexpr ExpressionVariableType value = OtherVariable;
-};
-
-template< typename T >
-struct  ExpressionVariableTypeGetter< T, true, false >
-{
-   static constexpr ExpressionVariableType value = ArithmeticVariable;
-};
-
-template< typename T >
-struct ExpressionVariableTypeGetter< T, false, true >
-{
-   static constexpr ExpressionVariableType value = VectorExpressionVariable;
-};
-
-////
-// Non-static expression templates might be passed on GPU, for example. In this
-// case, we cannot store ET operands using references but we need to make copies.
-template< typename T,
-          typename Device >
-struct OperandType
-{
-   using type = std::add_const_t< std::remove_reference_t< T > >;
-};
-
-template< typename T >
-struct OperandType< T, Devices::Host >
-{
-   using type = std::add_const_t< std::add_lvalue_reference_t< T > >;
-};
+   if( std::is_arithmetic< std::decay_t< T > >::value )
+      return ArithmeticVariable;
+   // vectors must be considered as an arithmetic type when used as RealType in another vector
+   if( IsArithmeticSubtype< T, V >::value )
+      return ArithmeticVariable;
+   if( HasEnabledExpressionTemplates< T >::value ||
+       HasEnabledStaticExpressionTemplates< T >::value ||
+       HasEnabledDistributedExpressionTemplates< T >::value
+   )
+      return VectorExpressionVariable;
+   if( IsArrayType< T >::value || IsStaticArrayType< T >::value )
+      return VectorExpressionVariable;
+   return OtherVariable;
+}
 
 } // namespace Expressions
 } // namespace Containers
diff --git a/src/TNL/Containers/Expressions/HorizontalOperations.h b/src/TNL/Containers/Expressions/HorizontalOperations.h
index 95a712f45e9e60e9a45bf42aa19f491aac101647..47b85d6e719d78382ac8c9d0f7c728bd9813715d 100644
--- a/src/TNL/Containers/Expressions/HorizontalOperations.h
+++ b/src/TNL/Containers/Expressions/HorizontalOperations.h
@@ -60,9 +60,9 @@ template< typename T1, typename T2 >
 struct Min
 {
    __cuda_callable__
-   static auto evaluate( const T1& a, const T2& b ) -> decltype( TNL::min( a , b ) )
+   static auto evaluate( const T1& a, const T2& b ) -> decltype( min( a , b ) )
    {
-      return TNL::min( a, b );
+      return min( a, b );
    }
 };
 
@@ -70,9 +70,9 @@ template< typename T1, typename T2 >
 struct Max
 {
    __cuda_callable__
-   static auto evaluate( const T1& a, const T2& b ) -> decltype( TNL::max( a, b ) )
+   static auto evaluate( const T1& a, const T2& b ) -> decltype( max( a, b ) )
    {
-      return TNL::max( a, b );
+      return max( a, b );
    }
 };
 
@@ -90,9 +90,9 @@ template< typename T1 >
 struct Abs
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::abs( a ) )
+   static auto evaluate( const T1& a ) -> decltype( abs( a ) )
    {
-      return TNL::abs( a );
+      return abs( a );
    }
 };
 
@@ -100,9 +100,9 @@ template< typename T1, typename T2 >
 struct Pow
 {
    __cuda_callable__
-   static auto evaluate( const T1& a, const T2& exp ) -> decltype( TNL::pow( a, exp ) )
+   static auto evaluate( const T1& a, const T2& exp ) -> decltype( pow( a, exp ) )
    {
-      return TNL::pow( a, exp );
+      return pow( a, exp );
    }
 };
 
@@ -110,9 +110,9 @@ template< typename T1 >
 struct Exp
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::exp( a ) )
+   static auto evaluate( const T1& a ) -> decltype( exp( a ) )
    {
-      return TNL::exp( a );
+      return exp( a );
    }
 };
 
@@ -120,9 +120,9 @@ template< typename T1 >
 struct Sqrt
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::sqrt( a ) )
+   static auto evaluate( const T1& a ) -> decltype( sqrt( a ) )
    {
-      return TNL::sqrt( a );
+      return sqrt( a );
    }
 };
 
@@ -130,9 +130,9 @@ template< typename T1 >
 struct Cbrt
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::cbrt( a ) )
+   static auto evaluate( const T1& a ) -> decltype( cbrt( a ) )
    {
-      return TNL::cbrt( a );
+      return cbrt( a );
    }
 };
 
@@ -140,9 +140,9 @@ template< typename T1 >
 struct Log
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::log( a ) )
+   static auto evaluate( const T1& a ) -> decltype( log( a ) )
    {
-      return TNL::log( a );
+      return log( a );
    }
 };
 
@@ -150,9 +150,9 @@ template< typename T1 >
 struct Log10
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::log10( a ) )
+   static auto evaluate( const T1& a ) -> decltype( log10( a ) )
    {
-      return TNL::log10( a );
+      return log10( a );
    }
 };
 
@@ -160,9 +160,9 @@ template< typename T1 >
 struct Log2
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::log2( a ) )
+   static auto evaluate( const T1& a ) -> decltype( log2( a ) )
    {
-      return TNL::log2( a );
+      return log2( a );
    }
 };
 
@@ -170,9 +170,9 @@ template< typename T1 >
 struct Sin
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::sin( a ) )
+   static auto evaluate( const T1& a ) -> decltype( sin( a ) )
    {
-      return TNL::sin( a );
+      return sin( a );
    }
 };
 
@@ -180,9 +180,9 @@ template< typename T1 >
 struct Cos
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::cos( a ) )
+   static auto evaluate( const T1& a ) -> decltype( cos( a ) )
    {
-      return TNL::cos( a );
+      return cos( a );
    }
 };
 
@@ -190,9 +190,9 @@ template< typename T1 >
 struct Tan
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::tan( a ) )
+   static auto evaluate( const T1& a ) -> decltype( tan( a ) )
    {
-      return TNL::tan( a );
+      return tan( a );
    }
 };
 
@@ -200,9 +200,9 @@ template< typename T1 >
 struct Asin
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::asin( a ) )
+   static auto evaluate( const T1& a ) -> decltype( asin( a ) )
    {
-      return TNL::asin( a );
+      return asin( a );
    }
 };
 
@@ -210,9 +210,9 @@ template< typename T1 >
 struct Acos
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::acos( a ) )
+   static auto evaluate( const T1& a ) -> decltype( acos( a ) )
    {
-      return TNL::acos( a );
+      return acos( a );
    }
 };
 
@@ -220,9 +220,9 @@ template< typename T1 >
 struct Atan
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::atan( a ) )
+   static auto evaluate( const T1& a ) -> decltype( atan( a ) )
    {
-      return TNL::atan( a );
+      return atan( a );
    }
 };
 
@@ -230,9 +230,9 @@ template< typename T1 >
 struct Sinh
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::sinh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( sinh( a ) )
    {
-      return TNL::sinh( a );
+      return sinh( a );
    }
 };
 
@@ -240,9 +240,9 @@ template< typename T1 >
 struct Cosh
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::cosh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( cosh( a ) )
    {
-      return TNL::cosh( a );
+      return cosh( a );
    }
 };
 
@@ -250,9 +250,9 @@ template< typename T1 >
 struct Tanh
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::tanh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( tanh( a ) )
    {
-      return TNL::tanh( a );
+      return tanh( a );
    }
 };
 
@@ -260,9 +260,9 @@ template< typename T1 >
 struct Asinh
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::asinh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( asinh( a ) )
    {
-      return TNL::asinh( a );
+      return asinh( a );
    }
 };
 
@@ -270,9 +270,9 @@ template< typename T1 >
 struct Acosh
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::acosh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( acosh( a ) )
    {
-      return TNL::acosh( a );
+      return acosh( a );
    }
 };
 
@@ -280,9 +280,9 @@ template< typename T1 >
 struct Atanh
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::atanh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( atanh( a ) )
    {
-      return TNL::atanh( a );
+      return atanh( a );
    }
 };
 
@@ -290,9 +290,9 @@ template< typename T1 >
 struct Floor
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::floor( a ) )
+   static auto evaluate( const T1& a ) -> decltype( floor( a ) )
    {
-      return TNL::floor( a );
+      return floor( a );
    }
 };
 
@@ -300,9 +300,9 @@ template< typename T1 >
 struct Ceil
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::ceil( a ) )
+   static auto evaluate( const T1& a ) -> decltype( ceil( a ) )
    {
-      return TNL::ceil( a );
+      return ceil( a );
    }
 };
 
@@ -310,9 +310,9 @@ template< typename T1 >
 struct Sign
 {
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::sign( a ) )
+   static auto evaluate( const T1& a ) -> decltype( sign( a ) )
    {
-      return TNL::sign( a );
+      return sign( a );
    }
 };
 
diff --git a/src/TNL/Containers/Expressions/StaticComparison.h b/src/TNL/Containers/Expressions/StaticComparison.h
index d12f1c12bdd0a5a4f63f1e3f507141d675f34706..af1bf17baf52579c7a586173215e7051069e3fff 100644
--- a/src/TNL/Containers/Expressions/StaticComparison.h
+++ b/src/TNL/Containers/Expressions/StaticComparison.h
@@ -19,8 +19,8 @@ namespace Expressions {
 
 template< typename T1,
           typename T2,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
 struct StaticComparison;
 
 /////
diff --git a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
index d08f2b02b76fe0c47b1ac4d141a6d6f9d85b5586..d2f01822bfbfa2876ef4f4e6fd07eab4a201bc1b 100644
--- a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
+++ b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
@@ -25,32 +25,28 @@ namespace Containers {
 namespace Expressions {
 
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value >
-struct StaticUnaryExpressionTemplate
-{};
+          template< typename > class Operation >
+struct StaticUnaryExpressionTemplate;
 
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type >
-struct IsExpressionTemplate< StaticUnaryExpressionTemplate< T1, Operation, T1Type > >
+          template< typename > class Operation >
+struct HasEnabledStaticExpressionTemplates< StaticUnaryExpressionTemplate< T1, Operation > >
 : std::true_type
 {};
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
-struct StaticBinaryExpressionTemplate
-{};
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
+struct StaticBinaryExpressionTemplate;
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation,
           ExpressionVariableType T1Type,
           ExpressionVariableType T2Type >
-struct IsExpressionTemplate< StaticBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
+struct HasEnabledStaticExpressionTemplates< StaticBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
 : std::true_type
 {};
 
@@ -62,6 +58,7 @@ template< typename T1,
           template< typename, typename > class Operation >
 struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, VectorExpressionVariable >
 {
+   using VectorOperandType = T1;
    using RealType = decltype( Operation< typename T1::RealType, typename T2::RealType >::
                               evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) );
 
@@ -115,6 +112,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab
    static_assert( IsStaticArrayType< T1 >::value,
                   "Left-hand side operand of static expression is not static, i.e. based on static vector." );
 
+   using VectorOperandType = T1;
    using RealType = decltype( Operation< typename T1::RealType, T2 >::
                               evaluate( std::declval<T1>()[0], std::declval<T2>() ) );
 
@@ -150,7 +148,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab
 
 protected:
    const T1& op1;
-   const T2& op2;
+   const T2 op2;
 };
 
 template< typename T1,
@@ -161,6 +159,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, Ve
    static_assert( IsStaticArrayType< T2 >::value,
                   "Right-hand side operand of static expression is not static, i.e. based on static vector." );
 
+   using VectorOperandType = T2;
    using RealType = decltype( Operation< T1, typename T2::RealType >::
                               evaluate( std::declval<T1>(), std::declval<T2>()[0] ) );
 
@@ -195,7 +194,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, Ve
    }
 
 protected:
-   const T1& op1;
+   const T1 op1;
    const T2& op2;
 };
 
@@ -203,8 +202,9 @@ protected:
 // Static unary expression template
 template< typename T1,
           template< typename > class Operation >
-struct StaticUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
+struct StaticUnaryExpressionTemplate
 {
+   using VectorOperandType = T1;
    using RealType = decltype( Operation< typename T1::RealType >::
                               evaluate( std::declval<T1>()[0] ) );
 
@@ -246,1020 +246,586 @@ protected:
 
 ////
 // Binary expressions addition
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator+( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator+( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Addition >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression subtraction
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator+( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator-( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression multiplication
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator+( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+operator*( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Binary expression division
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator+( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+operator/( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Division >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Comparison operator ==
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator+( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+bool
+operator==( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticComparison< ET1, ET2 >::EQ( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Comparison operator !=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator+( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+bool
+operator!=( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticComparison< ET1, ET2 >::NE( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Comparison operator <
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator+( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+bool
+operator<( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticComparison< ET1, ET2 >::LT( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Comparison operator <=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator+( const StaticUnaryExpressionTemplate< L1,LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+bool
+operator<=( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticComparison< ET1, ET2 >::LE( a, b );
 }
 
 ////
-// Binary expression subtraction
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Comparison operator >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+bool
+operator>( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticComparison< ET1, ET2 >::GT( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Comparison operator >=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator-( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+bool
+operator>=( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return Expressions::StaticComparison< ET1, ET2 >::GE( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Scalar product
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator-( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+operator,( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticExpressionSum( a * b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator-( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+dot( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return (a, b);
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Unary expression minus
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator-( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+operator-( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Minus >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Binary expression min
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator-( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+min( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Min >( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Binary expression max
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+max( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Max >( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Abs
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator-( const StaticUnaryExpressionTemplate< L1,LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+abs( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Abs >( a );
 }
 
 ////
-// Binary expression multiplication
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Pow
+template< typename ET1, typename Real,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+pow( const ET1& a, const Real& exp )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, Real, Pow >( a, exp );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Exp
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+exp( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Exp >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Sqrt
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+sqrt( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Sqrt >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Cbrt
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+cbrt( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Cbrt >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Log
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+log( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Log >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Log10
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+log10( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Log10 >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Log2
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+log2( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Log2 >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Sin
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticUnaryExpressionTemplate< L1,LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+sin( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Sin >( a );
 }
 
 ////
-// Binary expression division
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Cos
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+cos( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Cos >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Tan
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+tan( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Tan >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Asin
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+asin( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Asin >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Acos
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+acos( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Acos >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Atan
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+atan( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Atan >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Sinh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+sinh( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Sinh >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Cosh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+cosh( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Cosh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Tanh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticUnaryExpressionTemplate< L1,LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+tanh( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Tanh >( a );
 }
 
 ////
-// Comparison operator ==
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator==( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+// Asinh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+auto
+asinh( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Asinh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Acosh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-            const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+auto
+acosh( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Acosh >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Atanh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+auto
+atanh( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Atanh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Floor
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const StaticUnaryExpressionTemplate< T1, Operation >& b )
+auto
+floor( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Floor >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Ceil
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+ceil( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Ceil >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Sign
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+auto
+sign( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Sign >( a );
 }
 
 ////
-// Comparison operator !=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Cast
+template< typename ResultType,
+          typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 >,
+          // workaround: templated type alias cannot be declared at block level
+          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
 __cuda_callable__
-bool
-operator!=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+cast( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticUnaryExpressionTemplate< ET1, CastOperation >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Vertical operations
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+auto
+min( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionMin( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+auto
+argMin( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionArgMin( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-            const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+auto
+max( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionMax( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+auto
+argMax( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionArgMax( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const StaticUnaryExpressionTemplate< T1, Operation >& b )
+auto
+sum( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionSum( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+maxNorm( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return max( abs( a ) );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+auto
+l1Norm( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return sum( abs( a ) );
 }
 
-////
-// Comparison operator <
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+l2Norm( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   using TNL::sqrt;
+   return sqrt( sum( a * a ) );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+template< typename ET1,
+          typename Real,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+auto
+lpNorm( const ET1& a, const Real& p )
+// since (1.0 / p) has type double, TNL::pow returns double
+-> double
+//-> RemoveET< decltype(pow( StaticExpressionLpNorm( a, p ), 1.0 / p )) >
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   if( p == 1.0 )
+      return l1Norm( a );
+   if( p == 2.0 )
+      return l2Norm( a );
+   using TNL::pow;
+   return pow( sum( pow( abs( a ), p ) ), 1.0 / p );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+auto
+product( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionProduct( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+auto
+logicalAnd( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionLogicalAnd( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+auto
+logicalOr( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionLogicalOr( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+auto
+binaryAnd( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionBinaryAnd( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+binaryOr( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionBinaryOr( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator<( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
+#endif // DOXYGEN_ONLY
 
 ////
-// Comparison operator <=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator<=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
+// Output stream
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator<=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+std::ostream& operator<<( std::ostream& str, const StaticBinaryExpressionTemplate< T1, T2, Operation >& expression )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator<=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator<=( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-            const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator<=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator<=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator<=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator<=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operator >
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator>( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator>( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator>( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator>( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator>( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator>( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator>( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operator >=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator>=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator>=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator>=( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-            const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator>=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator>=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator>=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator>=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Unary operations
-
-////
-// Minus
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-operator-( const StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-////
-// Scalar product
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-operator,( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-operator,( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return StaticExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-operator,( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticExpressionSum( a * b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-operator,( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticExpressionSum( a * b );
-}
-
-#endif // DOXYGEN_ONLY
-
-////
-// Output stream
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const StaticBinaryExpressionTemplate< T1, T2, Operation >& expression )
-{
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression[ i ] << ", ";
-   str << expression[ expression.getSize() - 1 ] << " ]";
-   return str;
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression[ i ] << ", ";
+   str << expression[ expression.getSize() - 1 ] << " ]";
+   return str;
 }
 
 template< typename T,
@@ -1274,1008 +840,104 @@ std::ostream& operator<<( std::ostream& str, const StaticUnaryExpressionTemplate
 }
 
 } // namespace Expressions
-} // namespace Containers
-
-////
-// All operations are supposed to be in namespace TNL
-
-#ifndef DOXYGEN_ONLY
-
-////
-// Binary expression min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-auto
-min( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-auto
-min( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
 
-////
-// Binary expression max
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
+// Make all operators visible in the TNL::Containers namespace to be considered
+// even for StaticVector
+using Expressions::operator+;
+using Expressions::operator-;
+using Expressions::operator*;
+using Expressions::operator/;
+using Expressions::operator,;
+using Expressions::operator==;
+using Expressions::operator!=;
+using Expressions::operator<;
+using Expressions::operator<=;
+using Expressions::operator>;
+using Expressions::operator>=;
+
+// Make all functions visible in the TNL::Containers namespace
+using Expressions::dot;
+using Expressions::min;
+using Expressions::max;
+using Expressions::abs;
+using Expressions::pow;
+using Expressions::exp;
+using Expressions::sqrt;
+using Expressions::cbrt;
+using Expressions::log;
+using Expressions::log10;
+using Expressions::log2;
+using Expressions::sin;
+using Expressions::cos;
+using Expressions::tan;
+using Expressions::asin;
+using Expressions::acos;
+using Expressions::atan;
+using Expressions::sinh;
+using Expressions::cosh;
+using Expressions::tanh;
+using Expressions::asinh;
+using Expressions::acosh;
+using Expressions::atanh;
+using Expressions::floor;
+using Expressions::ceil;
+using Expressions::sign;
+using Expressions::cast;
+using Expressions::argMin;
+using Expressions::argMax;
+using Expressions::sum;
+using Expressions::maxNorm;
+using Expressions::l1Norm;
+using Expressions::l2Norm;
+using Expressions::lpNorm;
+using Expressions::product;
+using Expressions::logicalAnd;
+using Expressions::logicalOr;
+using Expressions::binaryAnd;
+using Expressions::binaryOr;
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
+} // namespace Containers
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-auto
-max( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-auto
-max( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Abs
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-abs( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-abs( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-////
-// Pow
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-__cuda_callable__
-auto
-pow( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-__cuda_callable__
-auto
-pow( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-exp( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-exp( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sqrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sqrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-cbrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-cbrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-log( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-log( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-log10( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-log10( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-log2( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-log2( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-cos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-cos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-tan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-tan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-asin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-asin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-acos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-acos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-atan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-atan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sinh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-cosh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-cosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-tanh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-tanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-asinh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-asinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-acosh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-acosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-atanh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-atanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-floor( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-floor( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-ceil( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-ceil( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sign( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sign( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType,
-          typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-__cuda_callable__
-auto
-cast( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-template< typename ResultType,
-          typename L1,
-          template< typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-__cuda_callable__
-auto
-cast( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-argMin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionArgMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-argMin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionArgMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-argMax( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionArgMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-argMax( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionArgMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sum( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionSum( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sum( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionSum( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionL1Norm( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionL1Norm( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return TNL::sqrt( StaticExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return TNL::sqrt( StaticExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-__cuda_callable__
-auto
-lpNorm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( StaticExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-__cuda_callable__
-auto
-lpNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( StaticExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-product( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionProduct( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-product( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionProduct( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-logicalOr( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-logicalOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-binaryOr( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-binaryOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-dot( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-dot( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return (a, b);
-}
-
-#endif // DOXYGEN_ONLY
+// Make all functions visible in the main TNL namespace
+using Containers::dot;
+using Containers::min;
+using Containers::max;
+using Containers::abs;
+using Containers::pow;
+using Containers::exp;
+using Containers::sqrt;
+using Containers::cbrt;
+using Containers::log;
+using Containers::log10;
+using Containers::log2;
+using Containers::sin;
+using Containers::cos;
+using Containers::tan;
+using Containers::asin;
+using Containers::acos;
+using Containers::atan;
+using Containers::sinh;
+using Containers::cosh;
+using Containers::tanh;
+using Containers::asinh;
+using Containers::acosh;
+using Containers::atanh;
+using Containers::floor;
+using Containers::ceil;
+using Containers::sign;
+using Containers::cast;
+using Containers::argMin;
+using Containers::argMax;
+using Containers::sum;
+using Containers::maxNorm;
+using Containers::l1Norm;
+using Containers::l2Norm;
+using Containers::lpNorm;
+using Containers::product;
+using Containers::logicalAnd;
+using Containers::logicalOr;
+using Containers::binaryAnd;
+using Containers::binaryOr;
 
 ////
 // Evaluation with reduction
diff --git a/src/TNL/Containers/Expressions/StaticVerticalOperations.h b/src/TNL/Containers/Expressions/StaticVerticalOperations.h
index 7c8477f4d8068373ce99b0366192d15bc1ea6b03..7deec166d95b6f05e6ac50c8d1e1494dfd2b5e97 100644
--- a/src/TNL/Containers/Expressions/StaticVerticalOperations.h
+++ b/src/TNL/Containers/Expressions/StaticVerticalOperations.h
@@ -11,6 +11,7 @@
 #pragma once
 
 #include <TNL/Math.h>
+#include <TNL/Containers/Expressions/TypeTraits.h>
 
 ////
 // By vertical operations we mean those applied across vector elements or
@@ -24,9 +25,10 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionMin( const Expression& expression )
 {
-   auto aux = expression[ 0 ];
+   using ResultType = RemoveET< typename Expression::RealType >;
+   ResultType aux = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
-      aux = TNL::min( aux, expression[ i ] );
+      aux = min( aux, expression[ i ] );
    return aux;
 }
 
@@ -34,8 +36,9 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionArgMin( const Expression& expression )
 {
+   using ResultType = RemoveET< typename Expression::RealType >;
    int arg = 0;
-   auto value = expression[ 0 ];
+   ResultType value = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
    {
       if( expression[ i ] < value )
@@ -51,9 +54,10 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionMax( const Expression& expression )
 {
-   auto aux = expression[ 0 ];
+   using ResultType = RemoveET< typename Expression::RealType >;
+   ResultType aux = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
-      aux = TNL::max( aux, expression[ i ] );
+      aux = max( aux, expression[ i ] );
    return aux;
 }
 
@@ -61,8 +65,9 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionArgMax( const Expression& expression )
 {
+   using ResultType = RemoveET< typename Expression::RealType >;
    int arg = 0;
-   auto value = expression[ 0 ];
+   ResultType value = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
    {
       if( expression[ i ] > value )
@@ -78,47 +83,19 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionSum( const Expression& expression )
 {
-   auto aux = expression[ 0 ];
+   using ResultType = RemoveET< typename Expression::RealType >;
+   ResultType aux = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
       aux += expression[ i ];
    return aux;
 }
 
-template< typename Expression >
-__cuda_callable__
-auto StaticExpressionL1Norm( const Expression& expression )
-{
-   auto aux = TNL::abs( expression[ 0 ] );
-   for( int i = 1; i < expression.getSize(); i++ )
-      aux += TNL::abs( expression[ i ] );
-   return aux;
-}
-
-template< typename Expression >
-__cuda_callable__
-auto StaticExpressionL2Norm( const Expression& expression )
-{
-   auto aux = expression[ 0 ] * expression[ 0 ];
-   for( int i = 1; i < expression.getSize(); i++ )
-      aux += expression[ i ] * expression[ i ];
-   return aux;
-}
-
-template< typename Expression, typename Real >
-__cuda_callable__
-auto StaticExpressionLpNorm( const Expression& expression, const Real& p )
-{
-   auto aux = TNL::pow( TNL::abs( expression[ 0 ] ), p );
-   for( int i = 1; i < expression.getSize(); i++ )
-      aux += TNL::pow( TNL::abs( expression[ i ] ), p );
-   return aux;
-}
-
 template< typename Expression >
 __cuda_callable__
 auto StaticExpressionProduct( const Expression& expression )
 {
-   auto aux = expression[ 0 ];
+   using ResultType = RemoveET< typename Expression::RealType >;
+   ResultType aux = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
       aux *= expression[ i ];
    return aux;
diff --git a/src/TNL/Containers/Expressions/TypeTraits.h b/src/TNL/Containers/Expressions/TypeTraits.h
index 606bb337aeb3438fdce861b54e949376652b8616..1024bb4653ecd28aa577494395520991c50f7e42 100644
--- a/src/TNL/Containers/Expressions/TypeTraits.h
+++ b/src/TNL/Containers/Expressions/TypeTraits.h
@@ -10,23 +10,115 @@
 
 #pragma once
 
-#include <type_traits>
+#include <TNL/TypeTraits.h>
 
 namespace TNL {
 namespace Containers {
 namespace Expressions {
 
+// trait classes used for the enabling of expression templates
 template< typename T >
-struct IsExpressionTemplate : std::false_type
+struct HasEnabledExpressionTemplates : std::false_type
 {};
 
 template< typename T >
-struct IsNumericExpression
-: std::integral_constant< bool,
-      std::is_arithmetic< T >::value ||
-      IsExpressionTemplate< T >::value >
+struct HasEnabledStaticExpressionTemplates : std::false_type
 {};
 
+template< typename T >
+struct HasEnabledDistributedExpressionTemplates : std::false_type
+{};
+
+
+// type aliases for enabling specific operators and functions using SFINAE
+template< typename ET1 >
+using EnableIfStaticUnaryExpression_t = std::enable_if_t<
+      HasEnabledStaticExpressionTemplates< ET1 >::value >;
+
+template< typename ET1, typename ET2 >
+using EnableIfStaticBinaryExpression_t = std::enable_if_t<
+      HasEnabledStaticExpressionTemplates< ET1 >::value ||
+      HasEnabledStaticExpressionTemplates< ET2 >::value >;
+
+template< typename ET1 >
+using EnableIfUnaryExpression_t = std::enable_if_t<
+      HasEnabledExpressionTemplates< ET1 >::value >;
+
+template< typename ET1, typename ET2 >
+using EnableIfBinaryExpression_t = std::enable_if_t<
+      // we need to avoid ambiguity with operators defined in Array (e.g. Array::operator==)
+      // so the first operand must not be Array
+      (
+         HasAddAssignmentOperator< ET1 >::value ||
+         HasEnabledExpressionTemplates< ET1 >::value ||
+         std::is_arithmetic< ET1 >::value
+      ) &&
+      (
+         HasEnabledExpressionTemplates< ET2 >::value ||
+         HasEnabledExpressionTemplates< ET1 >::value
+      ) >;
+
+template< typename ET1 >
+using EnableIfDistributedUnaryExpression_t = std::enable_if_t<
+      HasEnabledDistributedExpressionTemplates< ET1 >::value >;
+
+template< typename ET1, typename ET2 >
+using EnableIfDistributedBinaryExpression_t = std::enable_if_t<
+      // we need to avoid ambiguity with operators defined in Array (e.g. Array::operator==)
+      // so the first operand must not be Array
+      (
+         HasAddAssignmentOperator< ET1 >::value ||
+         HasEnabledDistributedExpressionTemplates< ET1 >::value ||
+         std::is_arithmetic< ET1 >::value
+      ) &&
+      (
+         HasEnabledDistributedExpressionTemplates< ET2 >::value ||
+         HasEnabledDistributedExpressionTemplates< ET1 >::value
+      ) >;
+
+
+// helper trait class for proper classification of expression operands using getExpressionVariableType
+template< typename T, typename V,
+          bool enabled = IsVectorType< V >::value >
+struct IsArithmeticSubtype
+: public std::integral_constant< bool,
+            // TODO: use std::is_assignable?
+            std::is_same< T, typename V::RealType >::value >
+{};
+
+template< typename T >
+struct IsArithmeticSubtype< T, T, true >
+: public std::false_type
+{};
+
+template< typename T >
+struct IsArithmeticSubtype< T, T, false >
+: public std::false_type
+{};
+
+template< typename T, typename V >
+struct IsArithmeticSubtype< T, V, false >
+: public std::is_arithmetic< T >
+{};
+
+
+// helper trait class (used in unit tests)
+template< typename R, bool enabled = ! HasEnabledStaticExpressionTemplates< R >::value >
+struct RemoveExpressionTemplate
+{
+   using type = R;
+};
+
+template< typename R >
+struct RemoveExpressionTemplate< R, false >
+{
+//   using type = StaticVector< R::getSize(), typename RemoveExpressionTemplate< typename R::RealType >::type >;
+   using type = typename RemoveExpressionTemplate< typename R::VectorOperandType >::type;
+};
+
+template< typename R >
+using RemoveET = typename RemoveExpressionTemplate< R >::type;
+
 } // namespace Expressions
 } // namespace Containers
 } // namespace TNL
diff --git a/src/TNL/Containers/Expressions/VerticalOperations.h b/src/TNL/Containers/Expressions/VerticalOperations.h
index 84d362e8aab01b704cdefac44ae0d7e0e6a7150d..f9e184e03a326b99853136e2e6e74c0916588ed8 100644
--- a/src/TNL/Containers/Expressions/VerticalOperations.h
+++ b/src/TNL/Containers/Expressions/VerticalOperations.h
@@ -31,7 +31,8 @@ auto ExpressionMin( const Expression& expression ) -> std::decay_t< decltype( ex
    using ResultType = std::decay_t< decltype( expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    auto reduction = [] __cuda_callable__ ( const ResultType& a, const ResultType& b ) { return TNL::min( a, b ); };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, fetch, std::numeric_limits< ResultType >::max() );
 }
@@ -43,7 +44,8 @@ auto ExpressionArgMin( const Expression& expression )
    using ResultType = std::decay_t< decltype( expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    auto reduction = [] __cuda_callable__ ( IndexType& aIdx, const IndexType& bIdx, ResultType& a, const ResultType& b ) {
       if( a > b ) {
          a = b;
@@ -61,7 +63,8 @@ auto ExpressionMax( const Expression& expression ) -> std::decay_t< decltype( ex
    using ResultType = std::decay_t< decltype( expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    auto reduction = [] __cuda_callable__ ( const ResultType& a, const ResultType& b ) { return TNL::max( a, b ); };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, fetch, std::numeric_limits< ResultType >::lowest() );
 }
@@ -73,7 +76,8 @@ auto ExpressionArgMax( const Expression& expression )
    using ResultType = std::decay_t< decltype( expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    auto reduction = [] __cuda_callable__ ( IndexType& aIdx, const IndexType& bIdx, ResultType& a, const ResultType& b ) {
       if( a < b ) {
          a = b;
@@ -91,37 +95,8 @@ auto ExpressionSum( const Expression& expression ) -> std::decay_t< decltype( ex
    using ResultType = std::decay_t< decltype( expression[0] + expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
-   return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 );
-}
-
-template< typename Expression >
-auto ExpressionL1Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] + expression[0] ) >
-{
-   using ResultType = std::decay_t< decltype( expression[0] + expression[0] ) >;
-   using IndexType = typename Expression::IndexType;
-
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::abs( expression[ i ] ); };
-   return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 );
-}
-
-template< typename Expression >
-auto ExpressionL2Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) >
-{
-   using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >;
-   using IndexType = typename Expression::IndexType;
-
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ] * expression[ i ]; };
-   return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 );
-}
-
-template< typename Expression, typename Real >
-auto ExpressionLpNorm( const Expression& expression, const Real& p ) -> std::decay_t< decltype( TNL::pow( expression[0], p ) ) >
-{
-   using ResultType = std::decay_t< decltype( TNL::pow( expression[0], p ) ) >;
-   using IndexType = typename Expression::IndexType;
-
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::pow( TNL::abs( expression[ i ] ), p ); };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 );
 }
 
@@ -131,7 +106,8 @@ auto ExpressionProduct( const Expression& expression ) -> std::decay_t< decltype
    using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::multiplies<>{}, fetch, (ResultType) 1 );
 }
 
@@ -141,7 +117,8 @@ auto ExpressionLogicalAnd( const Expression& expression ) -> std::decay_t< declt
    using ResultType = std::decay_t< decltype( expression[0] && expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::logical_and<>{}, fetch, std::numeric_limits< ResultType >::max() );
 }
 
@@ -151,7 +128,8 @@ auto ExpressionLogicalOr( const Expression& expression ) -> std::decay_t< declty
    using ResultType = std::decay_t< decltype( expression[0] || expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::logical_or<>{}, fetch, (ResultType) 0 );
 }
 
@@ -161,7 +139,8 @@ auto ExpressionBinaryAnd( const Expression& expression ) -> std::decay_t< declty
    using ResultType = std::decay_t< decltype( expression[0] & expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::bit_and<>{}, fetch, std::numeric_limits< ResultType >::max() );
 }
 
@@ -171,7 +150,8 @@ auto ExpressionBinaryOr( const Expression& expression ) -> std::decay_t< decltyp
    using ResultType = std::decay_t< decltype( expression[0] | expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::bit_or<>{}, fetch, (ResultType) 0 );
 }
 
diff --git a/src/TNL/Containers/StaticVector.h b/src/TNL/Containers/StaticVector.h
index 2fe136ac951d4c02bb339e4c0edcee43f3c3b7d8..60b6a60f873b2e6b6ffecd8ee0089ddc54931799 100644
--- a/src/TNL/Containers/StaticVector.h
+++ b/src/TNL/Containers/StaticVector.h
@@ -172,11 +172,18 @@ public:
    operator StaticVector< Size, OtherReal >() const;
 };
 
+// Enable expression templates for StaticVector
+namespace Expressions {
+   template< int Size, typename Real >
+   struct HasEnabledStaticExpressionTemplates< StaticVector< Size, Real > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/StaticVector.hpp>
-#include <TNL/Containers/StaticVectorExpressions.h>
 
 // TODO: move to some other source file
 namespace TNL {
diff --git a/src/TNL/Containers/StaticVectorExpressions.h b/src/TNL/Containers/StaticVectorExpressions.h
deleted file mode 100644
index fdaf7cf70fb5a894bce285bac7f4bc6a359ab878..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/StaticVectorExpressions.h
+++ /dev/null
@@ -1,774 +0,0 @@
-/***************************************************************************
-                          StaticVectorExpressions.h  -  description
-                             -------------------
-    begin                : Apr 19, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-#ifndef DOXYGEN_ONLY
-
-#include <TNL/Containers/Expressions/StaticExpressionTemplates.h>
-
-#include "StaticVector.h"
-
-namespace TNL {
-namespace Containers {
-// operators must be defined in the same namespace as the first operand, otherwise
-// they may not be considered by the compiler (e.g. inside pybind11's macros)
-// namespace Containers { Overriden operators should be in namespace TNL
-
-////
-// Addition
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator+( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Addition >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator+( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Addition >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-operator+( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Addition >( a, b );
-}
-
-////
-// Subtraction
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator-( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Subtraction >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator-( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Subtraction >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-operator-( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Subtraction >( a, b );
-}
-
-////
-// Multiplication
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator*( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Multiplication >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator*( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Multiplication >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-operator*( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Multiplication >( a, b );
-}
-
-////
-// Division
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator/( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Division >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator/( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Division >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-operator/( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Division >( a, b );
-}
-
-////
-// Comparison operations - operator ==
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator==( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::EQ( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator==( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::EQ( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-bool operator==( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::EQ( a, b );
-}
-
-////
-// Comparison operations - operator !=
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator!=( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::NE( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator!=( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::NE( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-bool operator!=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::NE( a, b );
-}
-
-////
-// Comparison operations - operator <
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator<( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::LT( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator<( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::LT( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-bool operator<( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::LT( a, b );
-}
-
-////
-// Comparison operations - operator <=
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator<=( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::LE( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator<=( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::LE( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-bool operator<=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::LE( a, b );
-}
-
-////
-// Comparison operations - operator >
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator>( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::GT( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator>( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::GT( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-bool operator>( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::GT( a, b );
-}
-
-////
-// Comparison operations - operator >=
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator>=( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::GE( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator>=( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::GE( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-bool operator>=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::GE( a, b );
-}
-
-////
-// Minus
-template< int Size, typename Real >
-__cuda_callable__
-auto
-operator-( const StaticVector< Size, Real >& a )
-{
-   return Expressions::StaticUnaryExpressionTemplate< StaticVector< Size, Real >, Expressions::Minus >( a );
-}
-
-////
-// Scalar product
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator,( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Containers::Expressions::StaticExpressionSum( a * b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator,( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Containers::Expressions::StaticExpressionSum( a * b );
-}
-
-template< typename Real1, int Size, typename Real2 >
-__cuda_callable__
-auto
-operator,( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Containers::Expressions::StaticExpressionSum( a * b );
-}
-
-} // namespace Containers
-
-////
-// Min
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-min( const Containers::StaticVector< Size, Real >& a, const ET& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ET, Containers::Expressions::Min >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-min( const ET& a, const Containers::StaticVector< Size, Real >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< ET, Containers::StaticVector< Size, Real >, Containers::Expressions::Min >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-min( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real1 >, Containers::StaticVector< Size, Real2 >, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Max
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-max( const Containers::StaticVector< Size, Real >& a, const ET& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ET, Containers::Expressions::Max >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-max( const ET& a, const Containers::StaticVector< Size, Real >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< ET, Containers::StaticVector< Size, Real >, Containers::Expressions::Max >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-max( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real1 >, Containers::StaticVector< Size, Real2 >, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-dot( const Containers::StaticVector< Size, Real >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-dot( const ET& a, const Containers::StaticVector< Size, Real >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, int Size, typename Real2 >
-__cuda_callable__
-auto
-dot( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b )
-{
-   return (a, b);
-}
-
-
-////
-// Abs
-template< int Size, typename Real >
-__cuda_callable__
-auto
-abs( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Abs >( a );
-}
-
-////
-// Power
-template< int Size, typename Real, typename ExpType >
-__cuda_callable__
-auto
-pow( const Containers::StaticVector< Size, Real >& a, const ExpType& exp )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ExpType, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< int Size, typename Real >
-__cuda_callable__
-auto
-exp( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sqrt( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< int Size, typename Real >
-__cuda_callable__
-auto
-cbrt( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< int Size, typename Real >
-__cuda_callable__
-auto
-log( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< int Size, typename Real >
-__cuda_callable__
-auto
-log10( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< int Size, typename Real >
-__cuda_callable__
-auto
-log2( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sine
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sin( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cosine
-template< int Size, typename Real >
-__cuda_callable__
-auto
-cos( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tangent
-template< int Size, typename Real >
-__cuda_callable__
-auto
-tan( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< int Size, typename Real >
-__cuda_callable__
-auto
-asin( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< int Size, typename Real >
-__cuda_callable__
-auto
-acos( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< int Size, typename Real >
-__cuda_callable__
-auto
-atan( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sinh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-cosh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-tanh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-asinh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-acosh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-atanh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< int Size, typename Real >
-__cuda_callable__
-auto
-floor( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< int Size, typename Real >
-__cuda_callable__
-auto
-ceil( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sign( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType, int Size, typename Real,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-__cuda_callable__
-cast( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a );
-}
-
-////
-// Vertical operations - min
-template< int Size, typename Real >
-__cuda_callable__
-auto
-min( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionMin( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-std::pair< int, Real >
-argMin( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionArgMin( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-max( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionMax( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-std::pair< int, Real >
-argMax( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionArgMax( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sum( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionSum( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-maxNorm( const Containers::StaticVector< Size, Real >& a )
-{
-   return max( abs( a ) );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-l1Norm( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionL1Norm( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-l2Norm( const Containers::StaticVector< Size, Real >& a )
-{
-   return TNL::sqrt( Containers::Expressions::StaticExpressionL2Norm( a ) );
-}
-
-template< int Size, typename Real, typename Real2 >
-__cuda_callable__
-auto
-lpNorm( const Containers::StaticVector< Size, Real >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::StaticExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-product( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionProduct( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-logicalOr( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionLogicalOr( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-binaryOr( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionBinaryOr( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-logicalAnd( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionLogicalAnd( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-binaryAnd( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionBinaryAnd( a );
-}
-
-} // namespace TNL
-#endif // DOXYGEN_ONLY
diff --git a/src/TNL/Containers/Vector.h b/src/TNL/Containers/Vector.h
index 6bec6932115b03a47696de90a7a560c31762c4a2..259081052c1d0c1241f190cdad4002f98b3bf2d0 100644
--- a/src/TNL/Containers/Vector.h
+++ b/src/TNL/Containers/Vector.h
@@ -174,7 +174,7 @@ public:
     */
    template< typename VectorExpression,
              typename...,
-             typename = std::enable_if_t< Expressions::IsExpressionTemplate< VectorExpression >::value > >
+             typename = std::enable_if_t< Expressions::HasEnabledExpressionTemplates< VectorExpression >::value && ! IsArrayType< VectorExpression >::value > >
    Vector& operator=( const VectorExpression& expression );
 
    /**
@@ -326,8 +326,15 @@ public:
    void segmentedScan( const VectorExpression& expression, FlagsArray& flags, IndexType begin = 0, IndexType end = 0 );
 };
 
+// Enable expression templates for Vector
+namespace Expressions {
+   template< typename Real, typename Device, typename Index, typename Allocator >
+   struct HasEnabledExpressionTemplates< Vector< Real, Device, Index, Allocator > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/Vector.hpp>
-#include <TNL/Containers/VectorExpressions.h>
diff --git a/src/TNL/Containers/VectorExpressions.h b/src/TNL/Containers/VectorExpressions.h
deleted file mode 100644
index 83d682e8bd50d38a7d16bf1b8895cb624aa021a2..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/VectorExpressions.h
+++ /dev/null
@@ -1,1098 +0,0 @@
-/***************************************************************************
-                          VectorExpressions.h  -  description
-                             -------------------
-    begin                : Jun 27, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <TNL/Containers/Expressions/ExpressionTemplates.h>
-
-#include "Vector.h"
-
-namespace TNL {
-namespace Containers {
-
-/**
- * \brief Addition of vector and vector expression.
- * @param a
- * @param b
- * @return 
- */
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Addition >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Addition >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator+( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator+( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator+( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Subtraction
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Subtraction >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Subtraction >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator-( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator-( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator-( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Multiplication
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Multiplication >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Multiplication >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator*( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator*( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator*( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Division
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Division >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Division >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator/( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator/( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator/( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Comparison operations - operator ==
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::EQ( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::EQ( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator==( const Vector< Real1, Device1, Index, Allocator >& a, const Vector< Real2, Device2, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device1, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device2, Index, Allocator >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator==( const VectorView< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index, Allocator >& b )
-{
-   using ConstView1 = VectorView< Real1, Device1, Index >;
-   using ConstView2 = typename Vector< Real2, Device2, Index, Allocator >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator==( const Vector< Real1, Device1, Index, Allocator >& a, const VectorView< Real2, Device2, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device1, Index, Allocator >::ConstViewType;
-   using ConstView2 = VectorView< Real2, Device2, Index >;
-   return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a.getConstView(), b );
-}
-
-////
-// Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::NE( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::NE( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator!=( const Vector< Real1, Device1, Index, Allocator >& a, const Vector< Real2, Device2, Index, Allocator >& b )
-{
-   return ! (a == b);
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator!=( const VectorView< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index, Allocator >& b )
-{
-   return ! (a == b);
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator!=( const Vector< Real1, Device1, Index, Allocator >& a, const VectorView< Real2, Device2, Index >& b )
-{
-   return ! (a == b);
-}
-
-////
-// Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::LT( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::LT( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() );
-}
-
-////
-// Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::LE( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::LE( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<=( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<=( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<=( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() );
-}
-
-////
-// Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::GT( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::GT( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() );
-}
-
-////
-// Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::GE( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::GE( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>=( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>=( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>=( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() );
-}
-
-////
-// Minus
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-operator-( const Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::UnaryExpressionTemplate< ConstView, Expressions::Minus >( a.getConstView() );
-}
-
-////
-// Scalar product
-#ifdef DOXYGEN_ONLY
-/**
- * \brief Computes scalar product of two vectors or vector expressions. Equivalent to \ref TNL::dot.
- *
- * @param a input vector or vector expression
- * @param b input vector or vector expression
- * @return scalar product of \e a and \e b.
- */
-template< typename ET1, typename ET2 >
-Real
-operator,( const ET1& a, const ET2& b ) {}
-#else
-
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-Real
-operator,( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   return Expressions::ExpressionSum( a.getConstView() * b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-Real
-operator,( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   return Expressions::ExpressionSum( a * b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator,( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   return Expressions::ExpressionSum( a.getConstView() * b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator,( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   return Expressions::ExpressionSum( a.getConstView() * b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator,( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::ExpressionSum( a.getConstView() * b.getConstView() );
-}
-#endif // DOXYGEN_ONLY
-
-} //namespace Containers
-
-////
-// All functions are supposed to be in namespace TNL
-
-////
-// Min
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Min >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Min >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-min( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-min( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-min( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Max
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Max >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Max >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-max( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-max( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-max( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-#ifdef DOXYGEN_ONLY
-/**
- * \brief Computes scalar product of vector and vector expression. Equivalent to \ref TNL::Containers::operator,.
- * 
- * @param a input vector
- * @param b input vector expression
- * @return scalar product of vector and vector expression
- */
-template< typename ET1, typename ET2 >
-auto
-dot( const ET1& a, const ET2& b ) {}
-#else
-
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-dot( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-dot( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-dot( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   return (a, b);
-}
-#endif // DOXYGEN_ONLY
-
-
-////
-// Abs
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-abs( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Abs >( a.getConstView() );
-}
-
-////
-// Power
-template< typename Real, typename Device, typename Index, typename Allocator, typename ExpType >
-auto
-pow( const Containers::Vector< Real, Device, Index, Allocator >& a, const ExpType& exp )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView, ExpType, Containers::Expressions::Pow >( a.getConstView(), exp );
-}
-
-////
-// Exp
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-exp( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Exp >( a.getConstView() );
-}
-
-////
-// Sqrt
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-sqrt( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sqrt >( a.getConstView() );
-}
-
-////
-// Cbrt
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-cbrt( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cbrt >( a.getConstView() );
-}
-
-////
-// Log
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-log( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log >( a.getConstView() );
-}
-
-////
-// Log10
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-log10( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log10 >( a.getConstView() );
-}
-
-////
-// Log2
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-log2( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log2 >( a.getConstView() );
-}
-
-////
-// Sine
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-sin( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sin >( a.getConstView() );
-}
-
-////
-// Cosine
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-cos( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cos >( a.getConstView() );
-}
-
-////
-// Tangent
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-tan( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tan >( a.getConstView() );
-}
-
-////
-// Asin
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-asin( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Asin >( a.getConstView() );
-}
-
-////
-// Acos
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-acos( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Acos >( a.getConstView() );
-}
-
-////
-// Atan
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-atan( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Atan >( a.getConstView() );
-}
-
-////
-// Sinh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-sinh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sinh >( a.getConstView() );
-}
-
-////
-// Cosh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-cosh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cosh >( a.getConstView() );
-}
-
-////
-// Tanh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-tanh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tanh >( a.getConstView() );
-}
-
-////
-// Asinh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-asinh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Asinh >( a.getConstView() );
-}
-
-////
-// Acosh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-acosh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Acosh >( a.getConstView() );
-}
-
-////
-// Atanh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-atanh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Atanh >( a.getConstView() );
-}
-
-////
-// Floor
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-floor( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Floor >( a.getConstView() );
-}
-
-////
-// Ceil
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-ceil( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Ceil >( a.getConstView() );
-}
-
-////
-// Sign
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-sign( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sign >( a.getConstView() );
-}
-
-////
-// Cast
-template< typename ResultType, typename Real, typename Device, typename Index, typename Allocator,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< decltype(a.getConstView()), Operation >( a.getConstView() );
-}
-
-////
-// Vertical operations - min
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-Real
-min( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionMin( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-std::pair< Index, std::decay_t< Real > >
-argMin( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionArgMin( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-Real
-max( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionMax( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-std::pair< Index, std::decay_t< Real > >
-argMax( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionArgMax( a.getConstView() );
-}
-
-/**
- * \brief Computes sum of all vector elements.
- * 
- * @param a input vector
- * @return sum of all vector elements
- */
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-sum( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionSum( a.getConstView() );
-}
-
-/**
- * \brief Computes maximum norm of a vector.
- * \anchor TNL__maxNorm
- * 
- * @param a input vector
- * @return  maximum norm
- */
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-maxNorm( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-l1Norm( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionL1Norm( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-l2Norm( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return TNL::sqrt( Containers::Expressions::ExpressionL2Norm( a.getConstView() ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator,
-          typename Real2 >
-auto
-lpNorm( const Containers::Vector< Real, Device, Index, Allocator >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ), 1.0 / p );
-}
-
-/**
- * \brief Computes product of all vector elements.
- * @param a
- * @return 
- */
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-product( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionProduct( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-logicalOr( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionLogicalOr( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-binaryOr( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionBinaryOr( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-logicalAnd( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionLogicalAnd( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-binaryAnd( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionBinaryAnd( a.getConstView() );
-}
-
-} // namespace TNL
diff --git a/src/TNL/Containers/VectorView.h b/src/TNL/Containers/VectorView.h
index 1a144ea5cde79951ee059f386859322eba18cf57..4c5262d30f4ec904d176da1a33313ad94d64cd0f 100644
--- a/src/TNL/Containers/VectorView.h
+++ b/src/TNL/Containers/VectorView.h
@@ -138,7 +138,7 @@ public:
     */
    template< typename VectorExpression,
              typename...,
-             typename = std::enable_if_t< Expressions::IsExpressionTemplate< VectorExpression >::value > >
+             typename = std::enable_if_t< Expressions::HasEnabledExpressionTemplates< VectorExpression >::value && ! IsArrayType< VectorExpression >::value > >
    VectorView& operator=( const VectorExpression& expression );
 
    /**
@@ -294,8 +294,15 @@ public:
    void segmentedScan( const VectorExpression& expression, FlagsArray& flags, IndexType begin = 0, IndexType end = 0 );
 };
 
+// Enable expression templates for VectorView
+namespace Expressions {
+   template< typename Real, typename Device, typename Index >
+   struct HasEnabledExpressionTemplates< VectorView< Real, Device, Index > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/VectorView.hpp>
-#include <TNL/Containers/VectorViewExpressions.h>
diff --git a/src/TNL/Containers/VectorViewExpressions.h b/src/TNL/Containers/VectorViewExpressions.h
deleted file mode 100644
index 6168b54066d74ac5151e40ed1100116353759556..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/VectorViewExpressions.h
+++ /dev/null
@@ -1,740 +0,0 @@
-/***************************************************************************
-                          VectorViewExpressions.h  -  description
-                             -------------------
-    begin                : Apr 27, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-#ifndef DOXYGEN_ONLY
-
-#include <TNL/Containers/Expressions/ExpressionTemplates.h>
-
-#include "VectorView.h"
-
-namespace TNL {
-namespace Containers {
-
-////
-// Addition
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Addition >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator+( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Addition >( a, b );
-}
-
-////
-// Subtraction
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Subtraction >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator-( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Subtraction >( a, b );
-}
-
-////
-// Multiplication
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Multiplication >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator*( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Multiplication >( a, b );
-}
-
-////
-// Division
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Division >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator/( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Division >( a, b );
-}
-
-////
-// Comparison operations - operator ==
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::EQ( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index >
-bool
-operator==( const VectorView< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device1, Index >, VectorView< Real2, Device2, Index > >::EQ( a, b );
-}
-
-////
-// Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::NE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index >
-bool
-operator!=( const VectorView< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& b )
-{
-   return ! (a == b);
-}
-
-////
-// Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::LT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool
-operator<( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::LT( a, b );
-}
-
-////
-// Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::LE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool
-operator<=( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::LE( a, b );
-}
-
-////
-// Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::GT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool
-operator>( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::GT( a, b );
-}
-
-////
-// Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::GE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool
-operator>=( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::GE( a, b );
-}
-
-////
-// Minus
-template< typename Real, typename Device, typename Index >
-auto
-operator-( const VectorView< Real, Device, Index >& a )
-{
-   return Expressions::UnaryExpressionTemplate< VectorView< Real, Device, Index >, Expressions::Minus >( a );
-}
-
-////
-// Scalar product
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator,( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::ExpressionSum( a * b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator,( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::ExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator,( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::ExpressionSum( a * b );
-}
-
-} // namespace Containers
-
-////
-// All functions are supposed to be in namespace TNL
-
-////
-// Min
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Min >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const ET& a, const Containers::VectorView< Real, Device, Index >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-min( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Max
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Max >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const ET& a, const Containers::VectorView< Real, Device, Index >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-max( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const ET& a, const Containers::VectorView< Real, Device, Index >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2 >
-auto
-dot( const Containers::VectorView< Real1, Device, Index1 >& a, const Containers::VectorView< Real2, Device, Index2 >& b )
-{
-   return (a, b);
-}
-
-
-////
-// Abs
-template< typename Real, typename Device, typename Index >
-auto
-abs( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Abs >( a );
-}
-
-////
-// Power
-template< typename Real, typename Device, typename Index, typename ExpType >
-auto
-pow( const Containers::VectorView< Real, Device, Index >& a, const ExpType& exp )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ExpType, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename Real, typename Device, typename Index >
-auto
-exp( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename Real, typename Device, typename Index >
-auto
-sqrt( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename Real, typename Device, typename Index >
-auto
-cbrt( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename Real, typename Device, typename Index >
-auto
-log( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename Real, typename Device, typename Index >
-auto
-log10( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename Real, typename Device, typename Index >
-auto
-log2( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sine
-template< typename Real, typename Device, typename Index >
-auto
-sin( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cosine
-template< typename Real, typename Device, typename Index >
-auto
-cos( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tangent
-template< typename Real, typename Device, typename Index >
-auto
-tan( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename Real, typename Device, typename Index >
-auto
-asin( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename Real, typename Device, typename Index >
-auto
-acos( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename Real, typename Device, typename Index >
-auto
-atan( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename Real, typename Device, typename Index >
-auto
-sinh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename Real, typename Device, typename Index >
-auto
-cosh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename Real, typename Device, typename Index >
-auto
-tanh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename Real, typename Device, typename Index >
-auto
-asinh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename Real, typename Device, typename Index >
-auto
-acosh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename Real, typename Device, typename Index >
-auto
-atanh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename Real, typename Device, typename Index >
-auto
-floor( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename Real, typename Device, typename Index >
-auto
-ceil( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename Real, typename Device, typename Index >
-auto
-sign( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType, typename Real, typename Device, typename Index,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename Real,
-          typename Device,
-          typename Index >
-Real
-min( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionMin( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-std::pair< Index, std::decay_t< Real > >
-argMin( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionArgMin( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-Real
-max( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionMax( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-std::pair< Index, std::decay_t< Real > >
-argMax( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionArgMax( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-sum( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionSum( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-maxNorm( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-l1Norm( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionL1Norm( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-l2Norm( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return TNL::sqrt( Containers::Expressions::ExpressionL2Norm( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index,
-          typename Real2 >
-auto
-lpNorm( const Containers::VectorView< Real, Device, Index >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::ExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-product( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionProduct( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-logicalOr( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionLogicalOr( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-binaryOr( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionBinaryOr( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-logicalAnd( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionLogicalAnd( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-binaryAnd( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionBinaryAnd( a );
-}
-
-} // namespace TNL
-#endif // DOXYGEN_ONLY
diff --git a/src/TNL/TypeTraits.h b/src/TNL/TypeTraits.h
index d617f2b42454bce2fad7a5d2ff69b685574723c9..3183460fef20a663705c02b641f8c866e2cde1c7 100644
--- a/src/TNL/TypeTraits.h
+++ b/src/TNL/TypeTraits.h
@@ -103,6 +103,33 @@ public:
     static constexpr bool value = type::value;
 };
 
+/**
+ * \brief Type trait for checking if T has operator+= taking one argument of type T.
+ */
+template< typename T >
+class HasAddAssignmentOperator
+{
+private:
+   template< typename U >
+   static constexpr auto check(U*)
+   -> typename
+      std::enable_if_t<
+         ! std::is_same<
+               decltype( std::declval<U>() += std::declval<U>() ),
+               void
+            >::value,
+         std::true_type
+      >;
+
+   template< typename >
+   static constexpr std::false_type check(...);
+
+   using type = decltype(check<T>(0));
+
+public:
+    static constexpr bool value = type::value;
+};
+
 /**
  * \brief Type trait for checking if T is an array type, e.g.
  *        \ref Containers::Array or \ref Containers::Vector.
@@ -118,6 +145,17 @@ struct IsArrayType
             HasSubscriptOperator< T >::value >
 {};
 
+/**
+ * \brief Type trait for checking if T is a vector type, e.g.
+ *        \ref Containers::Vector or \ref Containers::VectorView.
+ */
+template< typename T >
+struct IsVectorType
+: public std::integral_constant< bool,
+            IsArrayType< T >::value &&
+            HasAddAssignmentOperator< T >::value >
+{};
+
 /**
  * \brief Type trait for checking if T has a \e constexpr \e getSize method.
  */