Alexander Oh
Alexander Oh

Reputation: 25631

What are constrained templates?

Herb Sutters mentioned constrained templates (a.k.a. Concepts Lite) in the talk: Modern C++: What You Need to Know.

I know that boost has a concepts package in for ages, that allows one to pretty print error messages, when template deduction mechanism fails to find operators, functions or has access violation patterns.

I've encountered mentions on the isocpp blog that there is already an experimental branch of gcc implementing the document proposing Concepts Lite. However looking through the current C++14 draft I couldn't find any hints whether this will be already part of C++14.

So the questions are simple:

NOTE: if you wait long enough I'll try to get the gcc branch running and can at least say anything about the experimental implementation, which however does not imply the correctness of the syntax.

Upvotes: 6

Views: 441

Answers (1)

Casey
Casey

Reputation: 42554

Concepts Lite is the "constraints" part of a full concepts design for C++. It is described in great detail in N3701 "Concepts Lite". Chapter 2 is a short tutorial that quickly runs through the core principles and their application, which is great for folks that don't want to read through all 56 pages.

Concepts Lite will not be part of C++14, it will be released as a separate Technical Specification later this year. The latest rough draft for the TS wording is N3929 "Concepts Lite Specification".

There are a few different constraint syntax variants. The code example that Herb used in the talk:

auto mean(const Sequence& seq) {
  auto n = 0.0;
  for (auto x : seq)
    n += x;
  return n / seq.size();
}

is referred to as the "terse syntax" since it's a shorter equivalent of the verbose syntax:

template <typename __T>
  requires Sequence<__T>()
auto mean(const __T& seq) {
  auto n = 0.0;
  for (auto x : seq)
    n += x;
  return n / seq.size();
}

They both indicate that the function template mean can be instantiated with any type that models the Sequence concept. For the sake of simplicity, lets assume that the requirements for Sequence are only what our implementation of mean needs: (a) members begin & end that return iterators, and (b) member function size that returns some integral type. We could define the concept as:

template <typename T>
concept bool Sequence() {
  return requires(T t) {
    {t.size()} -> Integral;
    {t.begin()} -> InputIterator;
    {t.end()} -> InputIterator;
    requires Same<decltype(t.begin()), decltype(t.end())>();
  }
}

assuming straight-forward definitions of Integral, InputIterator, and Same. This concept definition ensures that, for some invented value t of the type T being tested:

  • t.size() is a valid expression, and it returns a type that models the Integral concept.
  • t.begin() is valid, and returns a type that models InputIterator.
  • Same for t.end().
  • The InputIterator returned by t.begin() has the same type as that returned by t.end().

Upvotes: 3

Related Questions