Loading [MathJax]/jax/output/HTML-CSS/config.js
Speclib  0.1.2
The library for writing better CUDA libraries
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules
sp::VariableUser< Subclass, Children > Class Template Reference

Base for anything that uses the expression variable system. More...

#include <Var.hpp>

Inheritance diagram for sp::VariableUser< Subclass, Children >:
[legend]

Public Types

template<typename Old , typename New >
using Substitute = std::conditional_t< std::is_same_v< Subclass, Old >, New, typename DeferSubclass< Old >::template ReplaceChildren< typename Children::template Substitute< Old, New >... > >
 Recursively substitute the given old user with the given new user. More...
 
using Vars = typename sp::cat_integer_sequences< typename Children::Vars... >::template sort<>::template unique<>
 The set of unbound variable names. More...
 
template<VariableName Name>
using VarType = typename VarTypeHelper< typename Children::template VarType< Name >... >::type
 The type of a named variable. More...
 
template<int I>
using ChildType = typename sp::TypeList< Children... >::template get< I >
 The type of the Ith child. More...
 

Public Member Functions

template<typename... Ts>
requires (!DeferSubclass<Ts...>::IsFullyBound)
constexpr decltype(auto) operator() (Ts &&... values) const
 Calls operator() on the result of binding this object to a set of variables. More...
 
template<int I>
constexpr auto & get ()
 Get the Ith child. More...
 
template<int I>
constexpr const auto & get () const
 Get the Ith child. More...
 
template<VariableName... Names, typename... Ts>
requires (sizeof...(Names) > 0)
constexpr auto bind (Ts &&... values) const
 Bind a specified set of values to the corresponding variables in this expression. More...
 
template<typename... Ts>
constexpr auto bind (Ts &&... values) const
 Bind a set of values to the expression's variables. More...
 
template<typename Old , typename New >
constexpr auto substitute (const New &newValue) const
 Substitute all instances of the given type with the the given new value. More...
 
template<typename... NewChildren>
constexpr auto replaceChildren (NewChildren &&... newChildren) const
 Replace the children of this variable user with the given new children. More...
 

Static Public Member Functions

static constexpr VariableName getUnusedVariableName (int i=0)
 Get an unused variable name. More...
 

Static Public Attributes

static constexpr bool IsFullyBound = Vars::Size == 0
 True if there are no unbound variables, and false if there are. More...
 
static constexpr bool IsFullyUnbound = (Children::IsFullyUnbound && ...)
 False if there are any bound variables, and true if there aren't. More...
 
static constexpr int ChildCount = sizeof...(Children)
 The number of children. More...
 

Protected Member Functions

template<typename... Ts>
constexpr VariableUser (Ts &&... children)
 Copy the arguments into the children tuple. More...
 

Detailed Description

template<typename Subclass, typename... Children>
class sp::VariableUser< Subclass, Children >

Base for anything that uses the expression variable system.

This class exists as an abstraction for anything that uses variables. This might be an expression, or it might be a system of multiple expressions that could be intended to be evaluated in a particular way. For example, one of the variables might be a buffer to write to rather than an expression to evaluate. That is why it has a binding mechanism rather than an evaluation mechanism. This design also allows for a partially bound object - where some of the variables are bound, but not all.

Most-derived classes that derive from this one (i.e: the Subclass template parameter) must define:

  • A default constructor if there are no bound variables.
  • A constructor taking one argument for each child (convertible to the type of that child) that calls the constructor for VariableUser.
  • A template alias (or other templated type) called ReplaceChildren. This should return the type that is equivalent to Subclass, but with its children (i.e: the arguments that would be passed as Children) changed to a given list of types. This is used by bind() to change variable types to bound variable types, and by Substitute to perform substitution recursively.

A subclasses may define an operator() that accepts no arguments. If it does, it should require IsFullyBound to be true. This class provides an operator() that accepts as many arguments as are unbound, provided this is not zero. This class has an operator()() that forwards its arguments to bind(), and then calls the subclass's operator()(). If wanted, it must be imported into the most derived class with a using declaration.

Template Parameters
SubclassA curiously recurring template parameter for the most-derived class.
ChildrenAll VariableUser-derived types that are directly used by the subclass. These must all be derived from VariableUser.

Member Typedef Documentation

◆ ChildType

template<typename Subclass , typename... Children>
template<int I>
using sp::VariableUser< Subclass, Children >::ChildType = typename sp::TypeList<Children...>::template get<I>

The type of the Ith child.

◆ Substitute

template<typename Subclass , typename... Children>
template<typename Old , typename New >
using sp::VariableUser< Subclass, Children >::Substitute = std::conditional_t<std::is_same_v<Subclass, Old>, New, typename DeferSubclass<Old>::template ReplaceChildren <typename Children::template Substitute<Old, New>...> >

Recursively substitute the given old user with the given new user.

An example use might be to replace one expression with another within a larger expression.

This is intended to be used for abstract algebra at compile time. To substitute a variable with a value at runtime, use bind().

Template Parameters
OldThe old user type to replace.
NewThe new user type to replace with.

◆ Vars

template<typename Subclass , typename... Children>
using sp::VariableUser< Subclass, Children >::Vars = typename sp::cat_integer_sequences<typename Children::Vars...>::template sort<>::template unique<>

The set of unbound variable names.

This is the union of the set of unbound variables for all children.

◆ VarType

template<typename Subclass , typename... Children>
template<VariableName Name>
using sp::VariableUser< Subclass, Children >::VarType = typename VarTypeHelper<typename Children::template VarType<Name>...>::type

The type of a named variable.

This is void if the variable does not exist. It is an error to use this if there are multiple variables with the same name but different types.

Template Parameters
NameThe name of the variable to get the type for.

Constructor & Destructor Documentation

◆ VariableUser()

template<typename Subclass , typename... Children>
template<typename... Ts>
constexpr sp::VariableUser< Subclass, Children >::VariableUser ( Ts &&...  children)
explicitconstexprprotected

Copy the arguments into the children tuple.

Member Function Documentation

◆ bind() [1/2]

template<typename Subclass , typename... Children>
template<VariableName... Names, typename... Ts>
requires (sizeof...(Names) > 0)
constexpr auto sp::VariableUser< Subclass, Children >::bind ( Ts &&...  values) const
constexpr

Bind a specified set of values to the corresponding variables in this expression.

Template Parameters
NamesThe names of the variables to bind.
Parameters
valuesThe values to replace each variable with, in the order given by Names.
Returns
Construct a copy object of this object, but with a type that is like Subclass and that has its variables replaced with the supplied concrete values.

◆ bind() [2/2]

template<typename Subclass , typename... Children>
template<typename... Ts>
constexpr auto sp::VariableUser< Subclass, Children >::bind ( Ts &&...  values) const
constexpr

Bind a set of values to the expression's variables.

Parameters
valuesThe values to substitute variables for. They must be provided in numerical (i.e: alphabetical) order.
Returns
Construct an object of a type that is like Subclass, but has its variables replaced with the supplied concrete values.

◆ get() [1/2]

template<typename Subclass , typename... Children>
template<int I>
constexpr auto & sp::VariableUser< Subclass, Children >::get ( )
constexpr

Get the Ith child.

◆ get() [2/2]

template<typename Subclass , typename... Children>
template<int I>
constexpr const auto & sp::VariableUser< Subclass, Children >::get ( ) const
constexpr

Get the Ith child.

◆ getUnusedVariableName()

template<typename Subclass , typename... Children>
static constexpr VariableName sp::VariableUser< Subclass, Children >::getUnusedVariableName ( int  i = 0)
staticconstexpr

Get an unused variable name.

If A is a variable user, and B is a variable user with the same variables as A, but with A::getUnusedVariableName(0) through A::getUnusedVariableName(N - 1) as well, then A::getUnusedVariableName(N) == B::getUnusedVariableName(0).

The returned variable name may come from a unicode private use area, as this is intended for use by automated algebra systems' temporary variables.

Parameters
iGuarantee non-collision when multiple variables are needed by setting this to a small unique non-negative value for each needed variable.
Returns
A variable name that is not used already by the variable user.

◆ operator()()

template<typename Subclass , typename... Children>
template<typename... Ts>
requires (!DeferSubclass<Ts...>::IsFullyBound)
constexpr decltype(auto) sp::VariableUser< Subclass, Children >::operator() ( Ts &&...  values) const
constexpr

Calls operator() on the result of binding this object to a set of variables.

For this to work, the return value of bind() must have an operator() that takes no arguments. Unfortunately, due to C++ name resolution rules that apply to CRTPs, the classes that want to use this when they're the most derived classes must import it using something like using VariableUser::operator();.

◆ replaceChildren()

template<typename Subclass , typename... Children>
template<typename... NewChildren>
constexpr auto sp::VariableUser< Subclass, Children >::replaceChildren ( NewChildren &&...  newChildren) const
constexpr

Replace the children of this variable user with the given new children.

Parameters
newChildrenThe new children.
Returns
A copy of this expression with the new children.

◆ substitute()

template<typename Subclass , typename... Children>
template<typename Old , typename New >
constexpr auto sp::VariableUser< Subclass, Children >::substitute ( const New &  newValue) const
constexpr

Substitute all instances of the given type with the the given new value.

Template Parameters
OldThe type to replace.
Parameters
newValueThe new value to use.
Returns
A copy of this expression with the substitution performed.

Member Data Documentation

◆ ChildCount

template<typename Subclass , typename... Children>
constexpr int sp::VariableUser< Subclass, Children >::ChildCount = sizeof...(Children)
staticconstexpr

The number of children.

◆ IsFullyBound

template<typename Subclass , typename... Children>
constexpr bool sp::VariableUser< Subclass, Children >::IsFullyBound = Vars::Size == 0
staticconstexpr

True if there are no unbound variables, and false if there are.

◆ IsFullyUnbound

template<typename Subclass , typename... Children>
constexpr bool sp::VariableUser< Subclass, Children >::IsFullyUnbound = (Children::IsFullyUnbound && ...)
staticconstexpr

False if there are any bound variables, and true if there aren't.