{"id":17977614,"url":"https://github.com/martinmoene/wholevalue","last_synced_at":"2026-03-27T02:04:23.008Z","repository":{"id":4714841,"uuid":"5862844","full_name":"martinmoene/WholeValue","owner":"martinmoene","description":"Whole value idiom made easy in C++","archived":false,"fork":false,"pushed_at":"2012-10-18T13:40:11.000Z","size":188,"stargazers_count":8,"open_issues_count":1,"forks_count":0,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-06T05:34:34.145Z","etag":null,"topics":["arithmetic-operators","c-plus-plus","idioms","quantity","type-safety","whole-value"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/martinmoene.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE_1_0.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-09-18T20:48:27.000Z","updated_at":"2023-03-05T13:56:46.000Z","dependencies_parsed_at":"2022-07-19T04:02:03.701Z","dependency_job_id":null,"html_url":"https://github.com/martinmoene/WholeValue","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/martinmoene/WholeValue","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinmoene%2FWholeValue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinmoene%2FWholeValue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinmoene%2FWholeValue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinmoene%2FWholeValue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinmoene","download_url":"https://codeload.github.com/martinmoene/WholeValue/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinmoene%2FWholeValue/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31008662,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T01:56:05.093Z","status":"online","status_checked_at":"2026-03-27T02:00:08.055Z","response_time":164,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arithmetic-operators","c-plus-plus","idioms","quantity","type-safety","whole-value"],"created_at":"2024-10-29T17:28:40.622Z","updated_at":"2026-03-27T02:04:22.997Z","avatar_url":"https://github.com/martinmoene.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"Whole Value Idiom\n===================\nThe whole value idiom[1] supports type-rich programming which, as Bjarne Stroustrup advocates, is an important means to improve software reliability, adding to this: �but most current infrastructure software doesn�t systematically use the techniques I suggest.� [2]\n\nApplying the whole value idiom where you would otherwise be tempted to use built-in types to represent domain values, gains you type checking and expressiveness.\n\nThis single-header library provides an easy, zero-overhead way to use the whole value idiom with built-in types in C++.[3]\n\nExample\n---------\n```C++\n#include \"whole_value.h\"\n\nWV_DEFINE_QUANTITY_TYPE( Integer, int )\n\nWV_DEFINE_TYPE( Year, Integer )\nWV_DEFINE_TYPE( Day, Integer )\n\nenum Month\n{\n    January=1, February, March, April, May, June,\n    July, August, September, October, November, December\n};\n\nclass Date\n{\npublic:\n   Date( Year year, Month month, Day day ) {}\n   // ...\n};\n\nint main()\n{\n    Date today = Date( Year(2012), July, Day(21) );  // OK\n//  today = Date( 2012, July, 21 );                  // compile-time error\n//  today = Date( Day(21), July, Year(2012) );       // compile-time error\n//  today = Date( July, Day(21), Year(2012) );       // compile-time error\n}\n\n// g++ -Wall -I../../include/ -I%BOOST_INCLUDE% -o wiki-example1 wiki-example1.cpp\n// cl -nologo -W3 -EHsc -I../../include/ -I%BOOST_INCLUDE% wiki-example1.cpp\n```\n\nOther libraries\n-----------------\nSimilar facilities.\n- Matthew Wilson's True Typedef in Imperfect C++ (Ch 18.4) and available from the [STLSoft C++ Libraries](http://stlsoft.org/).\n\nIf dimensions play a prime role in your computations, e.g. they are primarily physics-oriented, then you may be better off with libraries such as\n- [Boost.Units](http://www.boost.org/doc/libs/1_51_0/libs/units/) for zero-overhead dimensional analysis and unit/quantity manipulation and conversion.\n- Michael Kenniston's [Quantity Library](http://home.xnet.com/%7Emsk/quantity/quantity.html) ([Rationale](http://home.xnet.com/%7Emsk/quantity/quantity.html), Quantity [folder](http://www.xnet.com/%7Emsk/quantity)).\u003cbr\u003e\n- [PhysUnits-CT](https://github.com/martinmoene/PhysUnits-CT), a C++ library for compile-time dimensional analysis and unit/quantity manipulation and conversion. Derived from Michael Kenniston's Quantity Library.\n- [PhysUnits-RT](https://github.com/martinmoene/PhysUnits-RT), a C++ library for run-time dimensional analysis and unit/quantity manipulation and conversion. Derived from PhysUnits-CT.\n\nUsage\n-------\nThis library provides the following class templates to hold a value:\n* `whole_value` - just holds a value\n* `bits` - provides bitwise operations\n* `arithmetic` - provides arithmetic operations\n* `quantity` - provides a subset of arithmetic operations\n* `safe_bool` - a class template that implements the [Safe Bool idiom](http://www.artima.com/cppsource/safebool.html)\n\nDepending on your needs, you can define value types that do not interact with each other, or types that allow some interaction, for example with types that are convertible to the underlying type. The following examples range from strict to less so.\n\n### Type definitions\n\n```C++\n#include \"whole_value.h\"\nWV_DEFINE_VALUE_TYPE(Value, double)\n```\nThis type allows construction (default, initializer, copy) and assignment.\n\n```C++\n#include \"whole_value.h\"\nWV_DEFINE_BITS_TYPE(Bits, unsigned int)\n```\nThis type allows construction (default, initializer, copy), assignment, equality comparisons and bitwise operations xor, and, or, shift-left and shift-right.\n\n```C++\n#include \"whole_value.h\"\nWV_DEFINE_ARITHMETIC_TYPE(Real, double)\n```\nThis type allows construction (default, initializer, copy), assignment, and all comparison and arithmetic operations.\n\n```C++\n#include \"whole_value.h\"\nWV_DEFINE_QUANTITY_TYPE(Quantity, double)\n```\nThis type allows construction (default, initializer, copy), assignment, all comparison operations and a subset of the arithmetic operations. Think of this type as representing a dimension: the available operations do not change the type's 'dimension'. For example, the multiplication `Quantity *= Quantity` is not available (nor is `Quantity * Quantity`).\n\n```C++\n#include \"whole_value.h\"\nWV_DEFINE_SAFE_BOOL_TYPE(SafeBool)\n```\nThis creates a boolean type that has no adverse interactions with other types ([Safe Bool idiom](http://www.artima.com/cppsource/safebool.html)).\n\n```C++\n#include \"whole_value.h\"\nWV_DEFINE_SAFE_BOOL_TYPE(SafeBool)\nWV_DEFINE_SAFE_BOOL_TYPE(SafeBool2)\n\nint main()\n{\n    SafeBool safebool, safebool_( true );\n    SafeBool2 safebool2;\n\n    bool b = safebool;  // Ok\n//  int i = safebool;   // compile-time error\n\n    if ( safebool ) {}  // Ok\n\n    if ( safebool == safebool_ ) {}  // Ok\n//  if ( safebool == safebool2 ) {}  // compile-time error\n}\n\n// g++ -Wall -I../../include/ -I%BOOST_INCLUDE% -o wiki-example2 wiki-example2.cpp \u0026\u0026 wiki-example2\n// cl -nologo -W3 -EHsc -I../../include/ -I%BOOST_INCLUDE% wiki-example2.cpp \u0026\u0026 wiki-example2\n\n```\n\n### Sub-type definitions\n\n```C++\n#include \"whole_value.h\"\nWV_DEFINE_TYPE(A, Quantity)\nWV_DEFINE_TYPE(B, Quantity)\n\n```\nUse this if you want to distinguish values of type A and B as function arguments, but otherwise want to freely mix values of type A and B in expressions. Here `WV_DEFINE_TYPE` creates types A and B with Quantity as their common base type.\n\n### Interaction with underlying type\n\nTo allow interaction with the underlying type or types that are convertible to that, you can define the following preprocessor symbols before inclusion of the header file `whole_value.h`\n\n```C++\n// define:\n#define WV_ALLOW_CONVERSION_FROM_UNDERLYING_TYPE\n// or, one or more of:\n#define WV_ALLOW_CONVERSION_FROM_UNDERLYING_TYPE_FOR_VALUE\n#define WV_ALLOW_CONVERSION_FROM_UNDERLYING_TYPE_FOR_BITS\n#define WV_ALLOW_CONVERSION_FROM_UNDERLYING_TYPE_FOR_ARITHMETIC\n#define WV_ALLOW_CONVERSION_FROM_UNDERLYING_TYPE_FOR_QUANTITY\n\n#include \"whole_value.h\"\n```\n\n### Output\n\nTo make a type defined with `WV_DEFINE...` streamable, define the desired operator with or without io manipulators.\n\n```C++\n#include \"whole_value.h\"\n#include \u003ciomanip\u003e\n#include \u003ciostream\u003e\n\nWV_DEFINE_QUANTITY_TYPE(Quantity, double)\nWV_DEFINE_TYPE(Acceleration, Quantity)\nWV_DEFINE_TYPE(Speed, Quantity)\n\nWV_ADD_STREAM_INSERTION_OPERATOR(Quantity)\n// or\nWV_ADD_STREAM_INSERTION_OPERATOR_IOMANIP(Quantity, std::fixed \u003c\u003c std::setprecision(2) )\n\nint main()\n{\n    Acceleration acc(9.8);\n    Speed spd(330);\n    std::cout \u003c\u003c \"acc:\" \u003c\u003c acc \u003c\u003c \", spd:\" \u003c\u003c spd \u003c\u003c std::endl;\n}\n\n// g++ -Wall -I../../include/ -I%BOOST_INCLUDE% -o wiki-example3 wiki-example3.cpp \u0026\u0026 wiki-example3\n// cl -nologo -W3 -EHsc -I../../include/ -I%BOOST_INCLUDE% wiki-example3.cpp \u0026\u0026 wiki-example3\n```\nTo stream sub types, you only need to define a streaming operator for its base class.\n\n### Convenience functions\n\n```C++\n// absolute value:\n\ntemplate \u003ctypename T, typename U\u003e inline whole_value\u003cT,U\u003e abs( whole_value\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline  arithmetic\u003cT,U\u003e abs(  arithmetic\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline    quantity\u003cT,U\u003e abs(    quantity\u003cT,U\u003e const \u0026 x );\n\n// value as underlying type:\n\ntemplate \u003ctypename T, typename U\u003e inline T to_value( whole_value\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline T to_value(        bits\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline T to_value(  arithmetic\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline T to_value(    quantity\u003cT,U\u003e const \u0026 x );\n\n// value as integer (long):\n\ntemplate \u003ctypename T, typename U\u003e inline long to_integer( whole_value\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline long to_integer(  arithmetic\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline long to_integer(    quantity\u003cT,U\u003e const \u0026 x );\n\n// value as real (double):\n\ntemplate \u003ctypename T, typename U\u003e inline double to_real( whole_value\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline double to_real(  arithmetic\u003cT,U\u003e const \u0026 x );\ntemplate \u003ctypename T, typename U\u003e inline double to_real(    quantity\u003cT,U\u003e const \u0026 x );\n```\n\nDependencies\n-------------------------\n[Boost.Operators](http://www.boost.org/doc/libs/1_51_0/libs/utility/operators.htm) can be used to generate part of the logical and arithmetic operators of the `bits`, `arithmetic` and `quantity` class templates in this library. Note however that this is optional. If Boost.Operators is not used, the relevant operators are directly included in the classes in the conventional way.\n\nTo use Boost.Operators, `#define WV_USE_BOOST_OPERATORS` before inclusion of header file `whole_value.h`.\n\n```C++\n#define WV_USE_BOOST_OPERATORS // optional\n#include \"whole_value.h\"\n```\n\nBoost version 1.46.1 is known to work with the compilers mentioned below.\n\nPerformance\n------------\n\n```\nRelative performance (higher is better)\n\nCompiler        Option : double : Real  Real.B  Real.F : Derived  Derived.B  Derived.F\n-----------------------+--------+----------------------+------------------------------\nGCC 4.5.2         -O2  :  1     :  1     1       1     :   0.7      0.7        0.7\nMS VC6/VS6        -O2  :  1.2   :  1.2   0.1     0.1   :   0.95 a   0.05 b     0.05 c\nMS VC8/VS2005     -O2  :  1.1   :  0.4   0.4     0.4   :   0.4      0.4        0.4\nMS VC2010/VS2010  -O2  :  1.2   :  0.4   0.4     0.4   :   0.4      0.4        0.4\n\n                                                         a:0.009  b:0.01     c:0.007\n.B - with -DWV_USE_BOOST_OPERATORS\n.F - with -DWV_DEFINE_OPERATORS_IN_TERMS_OF_A_MINIMAL_NUMBER_OF_FUNDAMENTAL_OPERATORS\n\nWV_DEFINE_ARITHMETIC_TYPE(Real, double)\nWV_DEFINE_TYPE(Derived, Real)\n\nMeasured on AMD Athlon 64 X2 Dual Core Processor 5600+, 64kB L1 Data, 64kB L1 Instruction, 512kB L2, 3.2 GB RAM\na, b, c  on Intel Pentium M Processor, 32kB L1 Data, 32kB L1 Instruction, 2MB L2, 1.50 GHz\n```\n\nCompilers known to work\n-------------------------\n* GCC 4.5.2\n* MS VC6/VS6 - requires `using namespace wv;` for convenience functions and streaming operators (VC6 lacks [ADL](http://en.wikipedia.org/wiki/Argument-dependent_name_lookup)).\n* MS VC8/VS2005\n* MS VC2010/VS2010\n\nIdeas for improvement\n-----------------------\n* Immutable type variants\n\n\n### References\n[1] The whole value idiom was identified by Ward Cunningham[4] and Martin Fowler[5].\u003cbr\u003e[2] Bjarne Stroustrup. [Software Development for Infrastructure](http://www2.research.att.com/%7Ebs/Computer-Jan12.pdf). Computer, January 2012.\u003cbr\u003e[3] This library is inspired on the presentation by Mark Radford: [Design Experiences in C++, p.23](http://www.twonine.co.uk/articles/GenProgGoesLive.pdf#Page=23). 2005.\u003cbr\u003e[4] Ward Cunningham. [The CHECKS Pattern Language of Information Integrity](http://c2.com/ppr/checks.html). C2 Wiki, 1994.\u003cbr\u003e[5] Martin Fowler. [Quantity Pattern](http://martinfowler.com/eaaDev/quantity.html). Website.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinmoene%2Fwholevalue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinmoene%2Fwholevalue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinmoene%2Fwholevalue/lists"}