Scientific MetaProgramming In Modern C++

Metaprogramming

Template metaprogramming (TMP) is a metaprogramming technique in which templates are used by a compiler to generate temporary source code. (Wikipedia)

Scientific Programming

Meta programming is becoming more popular with the new features added to C++14/17 (trait library). Many physics libraries use this technique where efficiency is especially important or crucial. A good reference to learn the basics is the excellent book “C++ Template The Complete Guide” by the authors Vandevoorde, Josuttis and McGregor.

Template metaprogramming refers to the use of templates to perform computations at compiletime.
This comes in basically two flavors:
• Compute with numbers as usual, but during the compilation process
• Compute” with types, i.e., automatically map some types to other types
The former precomputes results to speed up the execution of the finished program, while the latter is something that is impossible to achieve during runtime.

Template metaprogramming can’t make use of loops and is therefore inherently recursive when performing nontrivial computations, and may become arbitrarily complex. An example of metaprogramming compile time Modern C++ single recursion to compute the factorial:

No loops in consexpr its a recursive process, can improve code efficiency …


	//C++14 programming compile-time using variable template (recursive template)
    template<int N>
    constexpr int factorial = factorial<N - 1>*N;

	//C++14 feature variable template
	constexpr auto w_resFactorl = factorial<3>;

Constexpr is compile-time key benefit of the constexpr it is statically initialized, free of race condition and static order issues.

/** TimePrm is a class for handling logical time
*/
class TimePrm
	{
	 ...
	
	public:
		constexpr TimePrm( double start_, double delta_, double stop_, bool aFixedT=true)
		: m_start(start_),
		  time_(start_), 
		  delta(delta_), 
		  stop(stop_), 
			timestep{}, // list-initialization ctor preferred
			m_stepMode{ eTimeStepMode::FIXED_TIME_STEP }
		 // m_fixedTimeStep(aFixedT)
		{ 
		}

// alias template code clarity
  template<typename Range>
  using EnableIfRngCopyable = std::enable_if_t<(std::is_copy_constructible<Range>::value)>;

  // meta programming using trait std library
  template<typename Range,  // numeric range such as ublas vector, valarray, expression template
           typename = EnableIfRngCopyable<Range>>
  auto Upwind1stDerivative( Range aRng) // let compiler deduce return (ensure decay of return type)
  {                                     // (top qualifiers such as const and reference stripped)
    using namespace boost;

    // c++17 std::size is constexpr, it should compile
    //static_assert( std::size(aRng) == EMcNeilDamBreakData<float>::DIM(), "Range size must equal to DB data");

    auto rng_size = std::distance( std::begin(aRng), std::end(aRng));
    auto iter_rng = make_iterator_range( std::begin(aRng), std::end(aRng));
    
    // trait to retrieve value of type
    return std::vector<range_value<Range>::type> {};
  }

SFINAE (Substitution Failure Is Not An Error) can be seen as a special case of template metaprogramming. Another example of Metaprogramming compile-time programming with Modern C++ is the use the template metafunction (type_trait “enable_if_t”) of the standard library. Modern C++17 constexpr

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *