Metaprogramming is another great feature of modern C++ that allows programs to redesign itself during compilation or run time. In C++17, another new feature about metaprogramming is introduced, logical operation metafunctions. These are variadic metafunctions that are conjunction
, disjunction
, and negation
which can be used for metaprogramming features of applications. In this post, we explain what logical operation metafunctions are.
Table of Contents
What are the logical operation metafunctions in modern C++?
Modern C++ has metaprogramming abilities which is a programming technique that a program can be compiled to read, create, analyse or transfer other program codes or it can compile itself, it can change the way of running codes while running.
In C++17, new variadic metafunctions are released for metaprogramming, these are conjunction
, conjunction
_v, disjunction
, disjunction
_v, and negation
, negation_v
. These traits short-circuit in the metaprogramming sense: template specializations that are not required to determine the result are not instantiated.
What is conjunction metafunction in modern C++?
In C++, conjunction
(std::conjunction
) or conjunction_v
(std::conjunction_v
) are a type trait that is defined in <type_traits> header that is used to design the logical conjunction between classes (data types, structs, classes). It is a kind of logical template of AND on a variadic pack of values.
Here is the simple definition of std::conjunction
:
1 2 3 |
template<class... _Bases> struct conjunction; |
Here is the simple definition of std::conjunction_v
which is a template of conjunction<...>::value
,
1 2 3 4 5 |
template<class... _Base> _INLINE_VAR _CONST_DATA bool conjunction_v = conjunction<_Base...>::value; |
Is there a simple example about conjunction in C++?
Here is a simple example which shows how you can use conjunction in C++.
1 2 3 4 5 6 7 |
using Int2 = std::integral_constant<int, 2>; using Int4 = std::integral_constant<int, 4>; std::cout << "Conjunction: " << std::conjunction< Int2, Int4 >::value << std::endl; // C++11 std::cout << "Conjunction: " << std::conjunction_v< Int2, Int4 > << std::endl; // C++17 |
You can find more details and examples about std::conjunction here,
What is disjunction (disjunction) metafunction in C++?
In C++, disjunction
(std::disjunction
) or disjunction_v
(std::disjunction_v
) are a type trait that is defined in <type_traits> header that is used to design the logical disjunction between classes (data types, structs, classes). It is a kind of logical template of OR on a variadic pack of values.
Here is the simple definition of std::disjunction,
1 2 3 |
template<class... _Bases> struct disjunction; |
Here is the simple definition of std::disjunction_v
which is a template of disjunction<...>::value
,
1 2 3 4 5 |
template<class... _Base> _INLINE_VAR _CONST_DATA bool disjunction_v = disjunction<_Base...>::value; |
Is there a simple example about disjunction?
Here is a simple example how you can use disjunction in C++.
1 2 3 4 5 6 7 |
using Int2 = std::integral_constant<int, 2>; using Int4 = std::integral_constant<int, 4>; std::cout << "Disjunction: " << std::disjunction< Int2, Int4 >::value << std::endl; // C++11 std::cout << "Disjunction: " << std::disjunction_v< Int2, Int4 > << std::endl; // C++17 |
Here above, std::conjunction<Int2, Int4>::value
evaluates to true
, which corresponds to the logical AND of Int2::value
(2) and Int4::value
(4) . The short-circuit behavior of std::conjunction
ensures that it stops evaluating as soon as it encounters a false
value, similar to how logical AND works.
You can find more details and examples about C++’s std::conjunction
here:
What is negation (std::negation) metafunction in modern C++?
In C++, negation
(std::negation
) or negation_v
(std::negation_v
) are a type trait that is defined in <type_traits> header that is used to design the logical negation between classes (data types, structs, classes). It is a kind of logical template of NOT on a variadic pack of values.
Here is the simple definition of std::conjunction,
1 2 3 4 5 6 7 |
template<class _Base> struct negation : integral_constant<bool, !_Base::value> { // negate type of _Base }; |
Is there a simple example about negation (std::negation) in C++?
Here is a simple example how you can use std::negation,
1 2 3 4 5 6 |
using Int2 = std::integral_constant<int, 2>; using Int4 = std::integral_constant<int, 4>; std::cout << std::negation<std::bool_constant<true>>::value << std::endl; |
You can find more details and examples about std::negation here,
Is there a full example about logical operation metafunctions in modern C++?
Here is a full example about logical operation metafunctions in modern C++,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <iostream> #include <type_traits> #include <typeinfo> class baseA {}; class baseB {}; class derivedA : public baseA {}; class derivedB : public baseB {}; int main() { // Let's define two integral constants using Int2 = std::integral_constant<int, 2>; using Int4 = std::integral_constant<int, 4>; // Let'S print the results (should be true, since both are non-zero) std::cout << "Conjunction of Integrals: " << std::conjunction< Int2, Int4 >::value << std::endl; // C++11 std::cout << "Conjunction of Integrals: " << std::conjunction_v< Int2, Int4 > << std::endl; std::cout << "Conjunction of Classes: " << std::conjunction_v< std::is_base_of<baseA, derivedA>, // C++17 std::is_base_of<baseB, derivedB> >; std::cout << "Disjunction of Integrals: " << std::disjunction< Int2, Int4 >::value << std::endl; std::cout << "Disjunction of Integrals: " << std::disjunction_v< Int2, Int4 > << std::endl; std::cout << "Disjunction of Classes: " << std::conjunction_v< std::is_base_of<baseA, derivedA>, // C++17 std::is_base_of<baseB, derivedB> >; std::cout << std::negation<std::bool_constant<true>>::value << std::endl; std::cout << std::negation_v<std::bool_constant<true>> << std::endl; system("pause"); return 0; } |
For more new details about std::set, you can check this paper P0013R1
C++ Builder is the easiest and fastest C and C++ compiler and IDE for building simple or professional applications on the Windows operating system. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise versions of C++ Builder and there is a trial version you can download from here.