Skip to main content
  • 2775 Accesses

Abstract

Template type names can be too complex for the user to use directly, as they may be verbose or they may require very complex syntax. So you should either publish a convenient typedef or allow users to ignore their type altogether.

This is a preview of subscription content, log in via an institution to check access.

Access this chapter

Chapter
USD 29.95
Price excludes VAT (USA)
  • Available as PDF
  • Read on any device
  • Instant download
  • Own it forever
eBook
USD 69.99
Price excludes VAT (USA)
  • Available as EPUB and PDF
  • Read on any device
  • Instant download
  • Own it forever
Softcover Book
USD 89.99
Price excludes VAT (USA)
  • Compact, lightweight edition
  • Dispatched in 3 to 5 business days
  • Free shipping worldwide - see info

Tax calculation will be finalised at checkout

Purchases are for personal use only

Institutional subscriptions

Notes

  1. 1.

    See also Section 12.3.

  2. 2.

    In symbols, (F(λ))(x) := F(λ(x)), where x may be a tuple.

  3. 3.

    In symbols again, (λ1+λ2)(x) := λ1(x)+λ2(x), where x may be a tuple.

  4. 4.

    We don’t explicitly list the code for operator+, which is almost identical, but we will use it freely in the rest of the section.

  5. 5.

    This can be fixed, by storing a static constant named min_number_of_arguments in every lambda implementation. Atomic lambdas, such as lambda_reference, will define it directly and derived lambdas will take the maximum from their nested types. Finally, this constant may be used for static assertions. We leave this as an exercise.

  6. 6.

    The rest of the chapter assumes that all the code presented up to now has been updated.

  7. 7.

    On the other hand, assignment and logical operators have a deducible return type. The former returns its first argument (a non-const reference); the latter returns bool. The new keyword decltype of C++0x would allow deducing this type automatically.

  8. 8.

    The name valarray is used on purpose, to remark that these techniques fit std::valarray.

  9. 9.

    In other words, a constructor that takes const valarray_interface<X,T>&. The details should follow easily and are left to the reader. The cast operator is required if operators return a type that you cannot modify directly (such as std::string).

  10. 10.

    See “price” and “quality” in the knapsack examples in Section 6.2.1.

  11. 11.

    Note that s is passed by value. According to the NVRO (Named Value Return Optimization), if there is only one return statement and the result is a named variable, the compiler can usually elide the copy, directly constructing the result on the caller’s stack.

  12. 12.

    See Section 9.2.8.

  13. 13.

    The example is obviously fictitious, as you cannot really add the operator to std::string.

  14. 14.

    See also Scott Meyers, “Effective Modern C++,” Item 29: “Assume that move operations are not present, not cheap, and not used.”

  15. 15.

    See the article on assertions by Alexandrescu and Torjo, which is also the source of the first sample in this paragraph: .

  16. 16.

    For extra clarity, we omitted the information collection phase (the estimation of the string length) from this example. In fact std::ostream does not need to be managed.

  17. 17.

    This is not obvious at all. In the last example of Section 9.3, we considered an agglomerate, namely bind_to(f)(argument)...(argument), whose syntax depends on the length of the chain. In fact, binding one argument of four yields a functor that takes 4-1=3 free arguments, and so on.

  18. 18.

    This allows you to present simplified code. You can easily add a storage policy as a template parameter.

  19. 19.

    If n is an integer of type int_t, the number of digits in base 10 for n is ceil(log10(n+1)). Assuming that a byte contains eight bits and that sizeof(int_t) is even, the largest integer is 256^sizeof(int_t)-1. When you put this in place of n, you’ll obtain a maximum number of ceil(log10(256)*sizeof(int_t)) ∼ (5/2)*sizeof(int_t) digits. You would add 1 for sign and 1 for the terminator.

  20. 20.

    See Section 1.4.7 on manipulators.

  21. 21.

    C++0x language extensions allow you to initialize some objects (including std::array) with a list in curly brackets. For more details, refer to http://en.cppreference.com/w/cpp/utility/initializer_list .

  22. 22.

    Exception safety may be a dependent issue. If the destructor of a proxy performs non-trivial work, it could throw.

Author information

Authors and Affiliations

Authors

Rights and permissions

Reprints and permissions

Copyright information

© 2015 Davide Di Gennaro

About this chapter

Cite this chapter

Gennaro, D.D. (2015). The Opaque Type Principle. In: Advanced Metaprogramming in Classic C++. Apress, Berkeley, CA. https://doi.org/10.1007/978-1-4842-1010-9_9

Download citation

Publish with us

Policies and ethics