How to design a type that can take an expression in the form of an algebraic expression with numbers and units, where Speed is the type, 23m / 10s could be an expression?
Example:
change_speed(Speed s); // better: the meaning of s is specified
// ...
change_speed(2.3); // error: no unit
change_speed(23m / 10s); // meters per second
EDIT This question raised the question if a literal in the form of 23m is possible at all.
EDIT the reference to the source has been removed from question for clarity. It can be found here
What you have to do is design types that when the expression is evaluated it yields the desired type. With
change_speed(23m / 10s);
We need 23m and 10s to each yield a type that when you divide them together gives you a Speed. If we have a
struct Meter
{
Meter(double value) : value(value) {}
double value;
};
struct Second
{
Second(double value) : value(value) {}
double value;
}
Speeds operator /(const Meter& m, const Second& s)
{
return Speed(m.value / s.value);
}
Then we just need to define literal operators for Meter and Second like
Meter operator "" _m(double value) { return Meter(value); }
Second operator "" _s(double value) { return Second(value); }
we have to use _m and _s to make these valid user defined literals. All literals besides those provided by the standard must start with a _.
Then
change_speed(23_m / 10_s)
becomes
change_speed(Meter(23) / Second(10))
which becomes
change_speed(Speed(2.3))
It sounds like you want something like a units/dimensional analysis type system. See for example Boost.Units.
The fundamental (length, time, etc.) units are defined similarly to the duration types in std::chrono - just with more than one (time) distinct dimension. The arithmetic operators are implemented to combine units into correctly-dimensioned compound types.
So, rather than defining Speed as an independent type, it's derived from the fundamental Metre and Second types (which are themselves instances of the length and time units, which are probably instances of a generic unit template differentiated by tag types).
If you want to write user-defined literals for SI units, there are examples on codeproject or in this project on Github - I haven't read through either and can't vouch for their quality, but the idea is fine.
From reading the section of the CPPCoreGuidelines I think that maybe you are confusing the intent of the section. The main point is:
Express ideas directly in code.
The concept being that the code change_speed(double s) is ambiguous because the units and identity of type is ambiguous. Furthermore change_speed(double speed_m_p_s) is no good because it is easy to get wrong. The suggestion is therefore that you explicitly create the input type. Something like:
enum class SpeedType {
M_p_S
Km_p_H
...
}
template<SpeedType type>
class Speed {
explicit Speed(double speed)
... // Some fully specified class that represents a speed.
template<SpeedType type>
void change_speed(Speed<type> s) { ...
change_speed(2.3) // Implicit conversion means this will be an error
change_speed(Speed<M_p_S>(2.3)) // It is clear to the reader and compiler that this is of type speed
// with unit of M_p_S. Go to the Speed class for more information.
This is not a perfect example. But conceptually, this is what they are trying to inform you with this section.
If I've understood the question correctly.
For required behaviour you can use next c++ features.
1) We're need class describes time. There are need classes in STL.
std::chrono::seconds, std::chrono::minutes and other. For literals using you must add:
#include <chrono>
using namespace std::chrono_literals;
auto thetime = 10m; // it's okey. the time have type std::chrono::minutes
2) We're need class describes distances. There aren't distance classes in STL.
3) We're need class speed.
4) We're need division operator for distance and time argument.
class distance
{
public:
inline constexpr distance(
const unsigned long long millimeters) :
millimeters_{ millimeters }
{
}
inline long double millimeters() const noexcept
{
return (millimeters_);
}
inline long double santimeters() const noexcept
{
return (millimeters_ / 10);
}
inline long double meters() const noexcept
{
return (millimeters_ / 1000);
}
inline long double kilometers() const noexcept
{
return (millimeters_ / 1000000);
}
private:
long double millimeters_; // it's must be least dimension unit
};
inline constexpr distance operator""_mm(const unsigned long long value)
{
return distance{ value };
}
inline constexpr distance operator""_cm(const unsigned long long value)
{
return distance{ value * 10 };
}
inline constexpr distance operator""_m(const unsigned long long value)
{
return distance{ value * 1000 };
}
inline constexpr distance operator""_km(const unsigned long long value)
{
return distance{ value * 1000000 };
}
// !
// it's need the same operators"" only for long long argument types
// !
class speed
{
public:
// ...
speed(long double)
{
}
// ...
};
template <typename _Rep>
speed operator/(
const distance& the_distance,
const std::chrono::duration<_Rep>& the_time)
{
// divide by zero!
return speed{ the_distance / the_time };
}
void speed_test(const speed&)
{
}
void foo()
{
using namespace std::chrono_literals;
speed_test(100_km / 21s);
}
Related
Is there some sort of compile-time switch statement that I can use to pass parameters to a constructor for a member variable? Right now, I have a controller (in the control systems sense, not the MVC sense) that I need to be able to configure its operating frequency at compile time and a filter whose parameters depend on the selected frequency. Here is a skeleton of how I've implemented it:
#include <cstdint>
class Filter {
public:
Filter(float p1, float p2) : p1(p1), p2{p2} {}
private:
float const p1;
float const p2;
};
class Controller {
public:
Controller(void) {}
private:
static constexpr uint32_t frequency = 200U;
Filter filter{frequency == 400U ? 3.0f : // p1
frequency == 200U ? 1.0f :
frequency == 50U ? 0.55f : 0f,
frequency == 400U ? 2.0f : // p2
frequency == 200U ? 9.0f :
frequency == 50U ? 37.1f : 0f,
};
static_assert(frequency == 400U || frequency == 200U || frequency == 50U, "Invalid frequency");
};
This is obviously very difficult to maintain for large numbers of frequencies, even for only two filter parameters (the real software has more). Every time I need to add support for a new frequency, I need to add code to n points in the code, where n is the number of parameters for the filter. What I would like is something like this:
Filter filter = frequency == 400U ? {3.0f, 2.0f} :
frequency == 200U ? {1.0f, 9.0f} :
frequency == 50U ? {0.55f, 37.1f} :
{0.0f, 0.0f};
Or, in my wilder dreams:
Filter filter = static_switch_map(frequency) {
400U: {3.0f, 2.0f},
200U: {1.0f, 9.0f},
50U: {0.55f, 37.1f},
};
The parameters for the filter are not formulaically determined and thus cannot be written as part of an expression. Some additional notes:
I am using c++14 extensions in clang and GNU C++.
I am open to using a higher c++ extension and compiler extensions specific to GNU C++, though c++14 in both clang and GNU C++ preferred. clang-only solutions are no good to me.
This is for use in an embedded environment; a run-time solution using switch plus new plus pointers is unacceptable because of the indirection performance hit, binary file bloat, and the un-safeness of memory allocation in the embedded environment.
The Filter class may be instantiated multiple times.
Solutions involving templates are okay; I'm only using floats right now because I'm porting someone's Matlab code, but I will eventually switch to fixed-point math.
Other solutions I have considered include:
Conditional compilation using macros and define (the frequency variable I'm using in the real code is a custom data type, so I'd need to use define and a C++ variable that have similar roles; I don't like the idea of having frequency defined in two locations -- that's going to lead to maintenance problems down the road).
Rewriting variables using a custom preprocessor during the build process. Too magical and will likely become a gotcha to someone in the future.
Enums. I haven't ruled these out, but I can't think of how to use them in a way that would improve the code without the abilities of Java enums and/or a Python-like *args expansion. Admittedly, I've only been writing C++ for about four months (non-consecutively) and only had a solid year of experience with C before that, so there's a good chance I'm missing something, syntax-wise.
Separate include file to contain the magic; in my project, all automatically generated files have a separate extension, so this works. However, I prefer to have simpler build scripts and keep as much of the logic in the C++ code as possible.
Put your switch in a factory method and make your constructor private, so that you are forced to use that method.
This way you'll have only one point to update in your code in future:
struct Filter {
static Filter create(int freq) {
switch(freq) {
case 0: return { 0, 1 };
case 2: return { 3, 7 };
default: return { 0, 0 };
}
}
private:
Filter(int, int) {}
};
int main() {
auto filter = Filter::create(2);
(void)filter;
}
If you want to use it also at compile-time, you can slightly change it as it follows (this requires C++14):
class Filter {
constexpr Filter(int i, int j)
: i{i}, j{j}
{}
public:
static constexpr Filter create(int freq) {
switch(freq) {
case 0: return { 0, 1 };
case 2: return { 3, 7 };
default: return { 0, 0 };
}
}
constexpr int get_i() const { return i; }
constexpr int get_j() const { return j; }
private:
int i;
int j;
};
int main() {
constexpr auto filter = Filter::create(2);
static_assert(filter.get_i() == 3, "!");
}
Of course, you can easily add a copy constructor or whatever to your Filter class. This is a minimal example to show how the pattern works, nothing more.
Another way to define them separately and use each constructor through a call to a factory method is based on delegating constructors:
template<int>
struct freq_tag {};
class Filter {
constexpr Filter(int i, int j)
: i{i}, j{j}
{}
constexpr Filter(freq_tag<0>): Filter{0, 1} {}
constexpr Filter(freq_tag<2>): Filter{3, 7} {}
template<int N>
constexpr Filter(freq_tag<N>): Filter{0, 0} {}
public:
template<int N>
constexpr static Filter create() {
return Filter{freq_tag<N>{}};
}
constexpr int get_i() const { return i; }
constexpr int get_j() const { return j; }
private:
int i;
int j;
};
int main() {
constexpr auto filter = Filter::create<2>();
static_assert(filter.get_i() == 3, "!");
}
It's mainly a matter of taste if compared to the switch-based solution, but for the fact that this one should work also in C++11.
Say I have a class representing automata, whose states are numbered (using state_t = unsigned) and whose transitons are also numbered (using transition_t = unsigned). Of course at some point I end up messing some calls because transition_t and state_t are the same type, so the compiler does not enforce the (semantic) type safety. That's easy to workaround by using a small class templated by a tag (struct transition_tag {}; struct state_tag {};), so now transition_t and state_t are incompatible, good!
/// Lightweight state/transition handle (or index).
template <typename Tag>
struct index_t_impl
{
using index_t = unsigned;
constexpr index_t_impl(index_t i)
: s{i}
{}
// Disallow index1_t i{index2_t{42}};
template <typename T>
index_t_impl(index_t_impl<T> t) = delete;
bool operator==(index_t_impl t) const
{
return s == t.s;
}
// Disallow index1_t{42} == index2_t{42};
template <typename T>
bool operator==(index_t_impl<T> t) const = delete;
/// Default ctor to please containers.
index_t_impl() = default;
constexpr operator index_t() const { return s; }
/// Be compliant with Boost integer ranges.
index_t_impl& operator++() { ++s; return *this; }
/// Be compliant with Boost integer ranges.
index_t_impl& operator--() { --s; return *this; }
private:
index_t s;
};
Further, I have two structures which are very much alike:
predecessors_t maps from a transition to its predecessor transition (in the shortest path). For efficiency, it's a std::vector<transition_t>.
path_t is a list of transition indexes. For efficiency it's a std::vector<transition_t>.
And then again I have this issue that I use std::vector<transition_t> for two completely different purposes. Of course, I could again introduce a wrapper templated by a tag, but then things become messy again. Public inheritance is very tempting (Thou shalt not inherit from std::vector)!
But really, I'm tired of ad-hoc solutions each time I want to introduce new types that are exactly like the base type, but just incompatible. Are there any recommendations on this regard? The public inheritance is really attractive, but wouldn't it introduce code bloat with tons on extra instantiations? Maybe the public composition (struct predecessors_t { std::vector<transition_t> v; };) as recommended by Crashworks (https://stackoverflow.com/a/4353276/1353549) is a better option that scales better?
Is there anything in sight in the future of C++ to address this new?
This issue of getting compiler-enforced semantic types can crop up in all sorts of situations, from your situation to co-ordinate systems with different origins (where the values are all the same type (eg. int), but semantically, the types must not be mixed, because they represent offsets from different origins (x,y,z=0,0,0)--this occurs frequently in mathematics, where, when graphing the quadrant with positive x and y, the origin is in the lower left, and computer science where it is very common to place the origin upper left) to spaceship navigation (more on this last below).
In 2012, Bjarne Stroustrup gave an interesting talk on what he called type-rich programming introducing compiler-enforced semantic type safety with C++11 using templates, user-defined literals, a claimed no run-time overhead implementation and even tales of lessons learned from the Mars Climate Observer snafu ($350M spacecraft + mission lost because of lack of enforced semantic type safety). You can see the part of the talk where he covers semantic types here: https://youtu.be/0iWb_qi2-uI?t=19m6s
I've written up a sample code excerpt based on Stroustrup's demo code, updated to current standards and with the required operator overloads implemented). Unlike Bjarne's example, this one actually compiles. ;)
Gist of this code can be found here: https://gist.github.com/u-007d/361221df5f8c7f3466f0f09dc96fb1ba
//Compiled with clang -std=c++14 -Weverything -Wno-c++98-compat main.cpp -o main
#include <iostream>
#include <string>
template<int M, int K, int S> //Meters, Kilograms, Seconds (MKS)
struct Unit
{
enum { m=M, kg=K, s=S };
};
template<typename Unit> //a magnitude with a unit
struct Value
{
double val; //the magnitude
constexpr explicit Value(double d) : val(d) {} //construct a Value from a double
};
//Basic Semantic Units for MKS domain
using Meter = Unit<1, 0, 0>;
using Kilogram = Unit<0, 1, 0>;
using Second = Unit<0, 0, 1>;
using Second2 = Unit<0, 0, 2>;
//Semantic Value Types for MKS domain
using Time = Value<Second>;
using Distance = Value<Meter>;
using Mass = Value<Kilogram>;
using Speed = Value<Unit<1, 0, -1>>; //Speed is meters/second
using Acceleration = Value<Unit<1, 0, -2>>; //Acceleration is meters/second^2
//Operator overloads to properly calculate units (incomplete; for demo purposes)
Speed operator/(const Distance& lhs, const Time& rhs)
{
return Speed(lhs.val / rhs.val);
}
Acceleration operator/(const Speed& lhs, const Time& rhs)
{
return Acceleration(lhs.val / rhs.val);
}
//Define literals
constexpr Distance operator"" _m(long double ld)
{
return Distance(static_cast<double>(ld));
}
constexpr Mass operator"" _kg(long double ld)
{
return Mass(static_cast<double>(ld));
}
constexpr Time operator"" _s(long double ld)
{
return Time(static_cast<double>(ld));
}
constexpr Acceleration operator"" _s2(long double ld)
{
return Acceleration(static_cast<double>(ld));
}
int main()
{
Speed sp = Distance(100)/Time(9.58); //Not bad, but units could be more convenient...
Distance d1 = 100.0_m; //A good distance to run a race
Speed sp1 = 100.0_m/9.58_s; //A human can run this fast
// Speed sp2 = 100.0_m/9.8_s2; //Error: speed is m/s, not m/s^2
// Speed sp3 = 100.0/9.8_s; //Error: 100 has no unit
Acceleration ac1 = sp1/0.5_s; //Faster than any human
return EXIT_SUCCESS;
}
In a function that takes several arguments of the same type, how can we guarantee that the caller doesn't mess up the ordering?
For example
void allocate_things(int num_buffers, int pages_per_buffer, int default_value ...
and later
// uhmm.. lets see which was which uhh..
allocate_things(40,22,80,...
A typical solution is to put the parameters in a structure, with named fields.
AllocateParams p;
p.num_buffers = 1;
p.pages_per_buffer = 10;
p.default_value = 93;
allocate_things(p);
You don't have to use fields, of course. You can use member functions or whatever you like.
If you have a C++11 compiler, you could use user-defined literals in combination with user-defined types. Here is a naive approach:
struct num_buffers_t {
constexpr num_buffers_t(int n) : n(n) {} // constexpr constructor requires C++14
int n;
};
struct pages_per_buffer_t {
constexpr pages_per_buffer_t(int n) : n(n) {}
int n;
};
constexpr num_buffers_t operator"" _buffers(unsigned long long int n) {
return num_buffers_t(n);
}
constexpr pages_per_buffer_t operator"" _pages_per_buffer(unsigned long long int n) {
return pages_per_buffer_t(n);
}
void allocate_things(num_buffers_t num_buffers, pages_per_buffer_t pages_per_buffer) {
// do stuff...
}
template <typename S, typename T>
void allocate_things(S, T) = delete; // forbid calling with other types, eg. integer literals
int main() {
// now we see which is which ...
allocate_things(40_buffers, 22_pages_per_buffer);
// the following does not compile (see the 'deleted' function):
// allocate_things(40, 22);
// allocate_things(40, 22_pages_per_buffer);
// allocate_things(22_pages_per_buffer, 40_buffers);
}
Two good answers so far, one more: another approach would be to try leverage the type system wherever possible, and to create strong typedefs. For instance, using boost strong typedef (http://www.boost.org/doc/libs/1_61_0/libs/serialization/doc/strong_typedef.html).
BOOST_STRONG_TYPEDEF(int , num_buffers);
BOOST_STRONG_TYPEDEF(int , num_pages);
void func(num_buffers b, num_pages p);
Calling func with arguments in the wrong order would now be a compile error.
A couple of notes on this. First, boost's strong typedef is rather dated in its approach; you can do much nicer things with variadic CRTP and avoid macros completely. Second, obviously this introduces some overhead as you often have to explicitly convert. So generally you don't want to overuse it. It's really nice for things that come up over and over again in your library. Not so good for things that come up as a one off. So for instance, if you are writing a GPS library, you should have a strong double typedef for distances in metres, a strong int64 typedef for time past epoch in nanoseconds, and so on.
(Note: post was originally tagged 'C`)
C99 onwards allows an extension to #Dietrich Epp idea: compound literal
struct things {
int num_buffers;
int pages_per_buffer;
int default_value
};
allocate_things(struct things);
// Use a compound literal
allocate_things((struct things){.default_value=80, .num_buffers=40, .pages_per_buffer=22});
Could even pass the address of the structure.
allocate_things(struct things *);
// Use a compound literal
allocate_things(&((struct things){.default_value=80,.num_buffers=40,.pages_per_buffer=22}));
You can't. That's why it is recommended to have as few function arguments as possible.
In your example you could have separate functions like set_num_buffers(int num_buffers), set_pages_per_buffer(int pages_per_buffer) etc.
You probably have noticed yourself that allocate_things is not a good name because it doesn't express what the function is actually doing. Especially I would not expect it to set a default value.
Just for completeness, you could use named arguments, when your call becomes.
void allocate_things(num_buffers=20, pages_per_buffer=40, default_value=20);
// or equivalently
void allocate_things(pages_per_buffer=40, default_value=20, num_buffers=20);
However, with the current C++ this requires quite a bit of code to be implemented (in the header file declaring allocate_things(), which must also declare appropriate external objects num_buffers etc providing operator= which return a unique suitable object).
---------- working example (for sergej)
#include <iostream>
struct a_t { int x=0; a_t(int i): x(i){} };
struct b_t { int x=0; b_t(int i): x(i){} };
struct c_t { int x=0; c_t(int i): x(i){} };
// implement using all possible permutations of the arguments.
// for many more argumentes better use a varidadic template.
void func(a_t a, b_t b, c_t c)
{ std::cout<<"a="<<a.x<<" b="<<b.x<<" c="<<c.x<<std::endl; }
inline void func(b_t b, c_t c, a_t a) { func(a,b,c); }
inline void func(c_t c, a_t a, b_t b) { func(a,b,c); }
inline void func(a_t a, c_t c, b_t b) { func(a,b,c); }
inline void func(c_t c, b_t b, a_t a) { func(a,b,c); }
inline void func(b_t b, a_t a, c_t c) { func(a,b,c); }
struct make_a { a_t operator=(int i) { return {i}; } } a;
struct make_b { b_t operator=(int i) { return {i}; } } b;
struct make_c { c_t operator=(int i) { return {i}; } } c;
int main()
{
func(b=2, c=10, a=42);
}
Are you really going to try to QA all the combinations of arbitrary integers? And throw in all the checks for negative/zero values etc?
Just create two enum types for minimum, medium and maximum number of buffers, and small medium and large buffer sizes. Then let the compiler do the work and let your QA folks take an afternoon off:
allocate_things(MINIMUM_BUFFER_CONFIGURATION, LARGE_BUFFER_SIZE, 42);
Then you only have to test a limited number of combinations and you'll have 100% coverage. The people working on your code 5 years from now will only need to know what they want to achieve and not have to guess the numbers they might need or which values have actually been tested in the field.
It does make the code slightly harder to extend, but it sounds like the parameters are for low-level performance tuning, so twiddling the values should not be perceived as cheap/trivial/not needing thorough testing. A code review of a change from
allocate_something(25, 25, 25);
...to
allocate_something(30, 80, 42);
...will likely get just a shrug/blown off, but a code review of a new enum value EXTRA_LARGE_BUFFERS will likely trigger all the right discussions about memory use, documentation, performance testing etc.
Suppose you have a function, and you call it a lot of times, every time the function return a big object. I've optimized the problem using a functor that return void, and store the returning value in a public member:
#include <vector>
const int N = 100;
std::vector<double> fun(const std::vector<double> & v, const int n)
{
std::vector<double> output = v;
output[n] *= output[n];
return output;
}
class F
{
public:
F() : output(N) {};
std::vector<double> output;
void operator()(const std::vector<double> & v, const int n)
{
output = v;
output[n] *= n;
}
};
int main()
{
std::vector<double> start(N,10.);
std::vector<double> end(N);
double a;
// first solution
for (unsigned long int i = 0; i != 10000000; ++i)
a = fun(start, 2)[3];
// second solution
F f;
for (unsigned long int i = 0; i != 10000000; ++i)
{
f(start, 2);
a = f.output[3];
}
}
Yes, I can use inline or optimize in an other way this problem, but here I want to stress on this problem: with the functor I declare and construct the output variable output only one time, using the function I do that every time it is called. The second solution is two time faster than the first with g++ -O1 or g++ -O2. What do you think about it, is it an ugly optimization?
Edit:
to clarify my aim. I have to evaluate the function >10M times, but I need the output only few random times. It's important that the input is not changed, in fact I declared it as a const reference. In this example the input is always the same, but in real world the input change and it is function of the previous output of the function.
More common scenario is to create object with reserved large enough size outside the function and pass large object to the function by pointer or by reference. You could reuse this object on several calls to your function. Thus you could reduce continual memory allocation.
In both cases you are allocating new vector many many times.
What you should do is to pass both input and output objects to your class/function:
void fun(const std::vector<double> & in, const int n, std::vector<double> & out)
{
out[n] *= in[n];
}
this way you separate your logic from the algorithm. You'll have to create a new std::vector once and pass it to the function as many time as you want. Notice that there's unnecessary no copy/allocation made.
p.s. it's been awhile since I did c++. It may not compile right away.
It's not an ugly optimization. It's actually a fairly decent one.
I would, however, hide output and make an operator[] member to access its members. Why? Because you just might be able to perform a lazy evaluation optimization by moving all the math to that function, thus only doing that math when the client requests that value. Until the user asks for it, why do it if you don't need to?
Edit:
Just checked the standard. Behavior of the assignment operator is based on insert(). Notes for that function state that an allocation occurs if new size exceeds current capacity. Of course this does not seem to explicitly disallow an implementation from reallocating even if otherwise...I'm pretty sure you'll find none that do and I'm sure the standard says something about it somewhere else. Thus you've improved speed by removing allocation calls.
You should still hide the internal vector. You'll have more chance to change implementation if you use encapsulation. You could also return a reference (maybe const) to the vector from the function and retain the original syntax.
I played with this a bit, and came up with the code below. I keep thinking there's a better way to do this, but it's escaping me for now.
The key differences:
I'm allergic to public member variables, so I made output private, and put getters around it.
Having the operator return void isn't necessary for the optimization, so I have it return the value as a const reference so we can preserve return value semantics.
I took a stab at generalizing the approach into a templated base class, so you can then define derived classes for a particular return type, and not re-define the plumbing. This assumes the object you want to create takes a one-arg constructor, and the function you want to call takes in one additional argument. I think you'd have to define other templates if this varies.
Enjoy...
#include <vector>
template<typename T, typename ConstructArg, typename FuncArg>
class ReturnT
{
public:
ReturnT(ConstructArg arg): output(arg){}
virtual ~ReturnT() {}
const T& operator()(const T& in, FuncArg arg)
{
output = in;
this->doOp(arg);
return this->getOutput();
}
const T& getOutput() const {return output;}
protected:
T& getOutput() {return output;}
private:
virtual void doOp(FuncArg arg) = 0;
T output;
};
class F : public ReturnT<std::vector<double>, std::size_t, const int>
{
public:
F(std::size_t size) : ReturnT<std::vector<double>, std::size_t, const int>(size) {}
private:
virtual void doOp(const int n)
{
this->getOutput()[n] *= n;
}
};
int main()
{
const int N = 100;
std::vector<double> start(N,10.);
double a;
// second solution
F f(N);
for (unsigned long int i = 0; i != 10000000; ++i)
{
a = f(start, 2)[3];
}
}
It seems quite strange(I mean the need for optimization at all) - I think that a decent compiler should perform return value optimization in such cases. Maybe all you need is to enable it.
This is kinda like my earlier question:
C++: Vector3 type "wall"?
Except, now, I want to do this to a builtin rather then a user created type.
So I want a type "Length" that behaves just like float -- except I'm going to make it's constructor explicit, so I have to explicitly construct Length objects (rather than have random conversions flying around).
Basically, I'm going into the type-a-lot camp.
Like suggested in a comment over at your other question you can use units from boost. This should be explicit and still manageable.
It sounds like you want to wrap a float primitive in your own class. Here's an example to get you started:
class Length
{
protected:
float value_;
public:
Length(float value) : value_(value) { }
static Length operator +(Length a, Length b) { return Length(a.value_ + b.value_); }
static Length operator -(Length a, Length b) { return Length(a.value_ - b.value_); }
static Length operator *(Length a, Length b) { return Length(a.value_ * b.value_); }
static Length operator /(Length a, Length b) { return Length(a.value_ / b.value_); }
};
But, using the boost Units library is a much better choice in the long run...