I have some code with fairly complicated logic that passing around angles in both radians and degrees. All of the variables are doubles. It would be helpful to add some additional guards to prevent passing a radians to a function that requires the value in degrees. The code below uses a struct and does work but requires .value to get the actual double back. Is it possible to template a primitive without using a struct? Is there a better way of doing this? I'm currently working C++17.
enum class AngleType
{
Degree,
Radian
};
template <AngleType T>
struct Angle
{
double value;
};
void example_function(Angle<AngleType::Radian> angle_radians) { };
A somewhat common way to do this is provide a conversion operator. Example:
#include <iostream>
#include <math.h>
template<int N, typename T>
struct AngleType
{
T value;
AngleType(T val) : value(val) {}
operator T() const noexcept
{
return value;
}
};
using AngleRadians = AngleType<0, double>;
using AngleDegrees = AngleType<1, double>;
void example_func(AngleRadians angle) {
std::cout << "angle in radians = " << angle << "\n";
}
int main(int argc, char **argv)
{
AngleRadians rad = M_PI;
AngleDegrees deg = 180;
example_func(rad);
example_func(deg); // <-- compiler error
}
It has its drawbacks, but it may be good enough for what you're trying to do.
Depends on what you really need, you could actually get rid of Angle and AngleType all together with User-defined literals.
Before starting, you need to decide the base unit you want to use. For my example, I will use radian as base unit.
The idea here is every time you attempt to use a number in degree, it would automatically convert that into radian.
// User-defined literal
constexpr auto operator"" _deg (long double deg)
{
return deg * PI / 180;
}
constexpr auto operator"" _deg (unsigned long long int deg)
{
return 1.0_deg * deg;
}
After defining this two, if you want to write a number in degree, you can simply use:
auto a = 90.0_deg;
And it would be equivalent to:
long double a = ((long double)90.0 * PI / 180);
To make it more consistent, you can also define a literal for _rad, and just use:
constexpr auto operator"" _rad (long double rad)
{
return rad;
}
constexpr auto operator"" _rad (unsigned long long int rad)
{
return 1.0_rad * rad;
}
Now every time you assign a number to something, you would do:
auto a = 3.14_rad, b = 180_deg;
However, do note that you cannot use literals on variables, so you can't do things like PI_rad. But, since we already settled the base unit as radian, then all variables are stored in radian anyways.
Also note that the parameter for those function are set to long double and unsigned long long int, as they were required by standard.
Related
I have been trying to solve following problem in C++. I would like to define a struct containing a configuration parameters for some software module. The configuration parameters are basically a floating point values and they are of two types:
parameters which are independent i.e. their values are given directly by some floating point numbers
parameters which are dependent i.e. their values are given by some expressions where the operands are the independent parameters
Here is an example
struct Configuration {
float param_independent_01;
float param_independent_02;
float param_dependent_01; // param_independent_01 + param_independent_02
float param_dependent_02; // 1.5f*param_independent_01/(param_independent_01 + param_independent_02)
};
I have been looking for a solution which enables the client code to only set values for the independent parameters and the dependent parameters values will be calculated automatically behind the scene.
Configuration config = {
param_independent_01 = 0.236f,
param_independent_02 = 0.728f
// param_dependent_01 = 0.236f + 0.728f
// param_dependent_02 = 1.5f*0.236f/(0.236f + 0.728f)
};
I suppose that the Configuration structure will be instantiated only once and the values of the parameters are known at compile time. Can anybody give me an advice how to do that in the C++?
One approach to achieve this behavior is to make use of C++'s constructor initialization list.
struct Configuration {
float param_independent_01;
float param_independent_02;
float param_dependent_01;
float param_dependent_02;
Configuration(float p1, float p2) :
param_independent_01(p1),
param_independent_02(p2),
param_dependent_01(p1 + p2),
param_dependent_02(1.5f * p1 / (p1 + p2)
)
{}
};
int main() {
Configuration config(0.236f, 0.728f);
return 0;
}
Or just inline constexpr variables in a namespace (can be put in a header).
This allows you to write some constexpr (consteval) functions to calculate the values too. (Not everything needs to be a class or a struct)
// header file
#pragma once
namespace configuration
{
inline constexpr float get_param_dependent_02(const float p1, const float p2)
{
return (1.5f * p1) / (p1+p2);
}
inline constexpr float param_independent_01{ 0.236f };
inline constexpr float param_independent_02{ 0.728f };
inline constexpr float param_dependent_01 = param_independent_01 + param_independent_02; // direct
inline constexpr float param_dependent_02 = get_param_dependent_02(param_independent_01, param_independent_02); // or through constexpr/consteval function
};
int main()
{
float f = configuration::param_dependent_02;
}
If you know the configuration is not going to change at runtime, you can implement a constexpr constructor for Configuration, and then define a constexpr Configuration variable. The construction will be done at compile time (see the generated assembler code for the godbolt link below).
If you wanted to make sure the configuration is not going to change at runtime, I would change Configuration into a class with private members, and just provide accessors for those members.
Notice also that the constructor may throw (due to a division by zero). If you want to take control of that situation, you may want to try-catch the setting of the dependent parameter 2 in the constructor's body.
[Demo]
#include <fmt/format.h>
#include <iostream>
class Configuration {
float param_independent_01;
float param_independent_02;
float param_dependent_01;
float param_dependent_02;
public:
constexpr Configuration(float p1, float p2)
: param_independent_01{p1}
, param_independent_02{p2}
, param_dependent_01{p1 + p2}
, param_dependent_02{(p1 * 1.5f)/param_dependent_01}
{}
auto get_pi1() { return param_independent_01; }
auto get_pi2() { return param_independent_02; }
auto get_pd1() { return param_dependent_01; }
auto get_pd2() { return param_dependent_02; }
friend std::ostream& operator<<(std::ostream& os, const Configuration& c) {
return os << fmt::format("pi1: {}\npi2: {}\npd1: {}\npd2: {}\n",
c.param_independent_01, c.param_independent_02,
c.param_dependent_01, c.param_dependent_02);
}
};
int main() {
constexpr Configuration c{3.14, 9.8};
std::cout << c;
}
No need for a class with a custom constructor, just do this:
struct Configuration
{
float param_independent_01 = 0; // Always initialize all class members.
float param_independent_02 = 0;
float param_dependent_01() const {return param_independent_01 + param_independent_02;}
float param_dependent_02() const {return 1.5f*param_independent_01/(param_independent_01 + param_independent_02);}
};
This is what I want to achieve: I have two user defined literals with one taking a long double value and returning a slope, and the other also taking a long double value and returning a humidity. Now I want to use both UDLs in one scope. Unfortunately, in both cases the unit is 'percentage'.
struct slope
{
long double val;
};
slope operator ""_perc(long double v)
{
slope s = {v};
return s;
}
struct humidity
{
long double val;
};
humidity operator ""_perc(long double v)
{
humidity h = {v};
return h;
}
void func(void)
{
slope s(0.0_perc);
humidity h(0.0_perc);
}
This is not possible since the signatures of two functions cannot only differ in the return type.
We could use namespaces:
namespace slp
{
slope operator ""_perc(long double v)
{
slope s = {v};
return s;
}
}
namespace hum
{
humidity operator ""_perc(long double v)
{
humidity h = {v};
return h;
}
}
but I dare state that user defined literals only make sense when used 'unqualified'. We do not want to use them this way:
void func(void)
{
slope s(slp::operator"" _perc(0.0));
humidity h(hum::operator"" _perc(0.0));
}
Since both UDLs shall be used in the same scope, we cannot use 'using' because of the ambiguity it creates:
using namespace slp;
using namespace hum;
or
using slp::operator ""_perc;
using hum::operator ""_perc;
So I am stuck.
Is there any - preferably elegant - way to achieve what I want?
One obvious solution is to come up with different names.
If you prefer to keep "percent" as a quantity, you can use a percent class and define constructors, per comment:
struct Percent {
long double value;
explicit constexpr Percent(long double v)
: value{v}
{
}
};
constexpr Percent operator""_perc(long double v) noexcept
{
return Percent(v);
}
struct slope {
long double val;
explicit slope(Percent pc)
: val{pc.value}
{
}
};
// humidity similar
You can define explicit conversion operators if you need slope and humidity to be aggregates.
You might cheat by creating extra scope (as lambda immediately executed):
void func(void)
{
auto s = [](){ using namespace slp; return 0.0_perc; }(); // slope
auto h = [](){ using namespace hum; return 0.0_perc; }(); // humidity
// ...
}
I'm trying to pass function of multiple arguments to other function. I know how to pass a function of single argument function to other function as it was described in C++ primer plus book.
However, I get an error when I'm trying to pass multiple arguments with class(poly_3d) to NR_method function.
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double));
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
NR_method(3.2, poly_3d);
system("PAUSE");
return 0;
}
double poly_3d(double x, constants cst) {
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
double NR_method(double a, double (*poly_3d)(double)) {
double c = (*poly_3d)(a);
return c;
}
So the error I'm getting is from NR_method(3.2, poly_3d) in main function. I know that if poly_3d was single arg, this would work.
If this is a horrible way to write codes, then any directions towards learning C++ more effectively for newbies would be much appreciated! Thanks
Take a look at the following code. We're using a template to make things look nicer.
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
/// Note that we take a ref now, no need to copy cst.
double poly_3d(double x, constants & cst)
{
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
/// Note that we take a ref now, no need to copy cst.
template <class F>
double NR_method(double a, constants & cst, F func)
{
return func(a, cst);
}
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
NR_method(3.2, cst, &poly_3d);
system("PAUSE");
return 0;
}
You are declaring the function poly_3d with 2 arguments but passing only one. I made a few changes on the code for you
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
double poly_3d(double x, constants cst);
double NR_method(double a, constants cst, double(*poly_3d)(double, constants));
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
printf("%f", NR_method(3.2, cst, poly_3d));
system("PAUSE");
return 0;
}
double poly_3d(double x, constants cst) {
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
double NR_method(double a, constants cst, double (*poly)(double, constants)) {
return (*poly)(a, cst);
}
Let's start by simplifying your code. (A minimal example removes distractions, allowing you to better focus on the actual issue.) It looks like you started to do this, but it can be taken further. After removing some stuff that is not needed to reproduce the compile error:
class constants {};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double));
int main() {
NR_method(3.2, poly_3d);
}
double poly_3d(double x, constants /*cst*/) {
return 3 * x;
}
double NR_method(double a, double (*poly_3d)(double)) {
return (*poly_3d)(a);
}
Now let's look at the error message:
error: invalid conversion from 'double (*)(double, constants)' to 'double (*)(double)'
This comes with an indication that the conversion is from poly_3d to the second argument of NR_method. If you look at those things, yes, that is the conversion you requested. The argument list for poly_3d is (double, constant), while the declared argument list for the second argument is just (double). There is a mismatch, which makes the conversion invalid. It's not all that different from the single-parameter case: the signatures must match. You can solve this by changing the argument's signature to math that of poly_3d.
Now, if you just make the signatures match, there is another problem in that NR_method does not have a constants value available. That is probably a logical error for you to work out. For a quick workaround to show the elimination of the compiler error, I'll add a local variable.
class constants {
};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double, constants)); // <-- Desired signature
int main() {
NR_method(3.2, poly_3d);
}
double poly_3d(double x, constants /*cst*/) {
return 3.0 * x;
}
double NR_method(double a, double (*poly_3d)(double, constants)) {
constants cst; // <-- Allows this to compile, but probably not what you want.
return (*poly_3d)(a, cst); // <-- Needed a second parameter here.
}
There are ways to make this work nicer (for example, a std::function may be more convenient than a function pointer), but explaining those would fall outside the scope of this question, especially since some decisions would depend on the bigger picture.
Since direct floating point comparisons are risky, i am writing one wrapper class for checking relational operations for floating point numbers.
#include<iostream>
#include <cmath>
template<unsigned int round_off_digits=10>
class FloatRelationalOperators
{
private:
inline static double calcEpsilonValue()
{
int localVar=round_off_digits;
double withLocalVar=pow(10, (localVar * -1 ));
double WithoutLocalVar=pow(10, (round_off_digits * -1 ));
std::cout<<"withLocalVar: "<<withLocalVar<<" "<<"WithoutLocalVar :"<<WithoutLocalVar;
return WithoutLocalVar;
}
public:
inline static bool notequal(double a,double b)
{
double res=fabs(a-b);
if( res <= calcEpsilonValue())
{
return true;
}
else
{
return false;
}
return false;
}
};
int main()
{
FloatRelationalOperators<>::notequal(10.1,10.0);
}
I am trying to calculate the epsilon value from max round off digits.
When i run the program, i got the result as follows,
withLocalVar: 1e-10 WithoutLocalVar :inf
Why my answer is wrong when non-type template parameter is used directly in the function?
Am I doing anything wrong?
round_off_digits is an unsigned value and you multiply it with -1 which makes a pretty big unsigned int. If you change it to int it works
http://cpp.sh/8yflj
I have a template class for graphs that takes a parameter for the weight type (could be unsigned, int or double). Also, for comparing doubles I use inline functions of the following type:
inline bool EpsLess(double x, double y, double epsilon = 1.e-10)
{
return x < y - epsilon;
}
inline bool EpsEqual(double x, double y, double epsilon = 1.e-10)
{
return !EpsLess(x,y) && !EpsLess(y,x);
}
Is the comparator in the following class skeleton safe ?
template <typename Weight>
class Graph
{
struct Edge
{
std::string from;
std::string to;
Weight weight;
};
struct LargestWeight
{
bool operator() (const Edge& e1, const Edge& e2) const
{
if (EpsEqual(e1.weight == e2.weight))
if (e1.from == e2.from)
return e1.to < e2.to;
else
return e1.from < e2.from;
return EpsLess(e2.weight, e1.weight);
}
};
// .. other stuff
};
Can I encounter unforeseen consequences when Weight type is unsigned or int ? Or is there a better way to implement the double comparison ?
This is exactly what templates are for.
I would suggest that you implement EpsLess() inside a template class that uses just the < and == operators. Something like:
template<typename Type> Compare {
public:
template<typename Ignore>
inline bool EpsLess(Type x, Type y, Ignore epsilon = Ignore())
{
return x < y;
}
};
Then specialize it for a double:
template<> Compare<double> {
public:
inline bool EpsLess(double x, double y, double epsilon = 1.e-10)
{
return x < y - epsilon;
}
};
You would invoke it like this:
if (Compare<Weight>::EpsEqual(e1.weight, e2.weight))
This will avoid a bunch of useless work for non-double cases, and get devolved to just an ordinary < operator.
Your homework assignment, then, is to reimplement EpsEqual() as a template function itself, in terms of the new EpsLess().
No, you can't trust the integer to double conversion in all cases.
Conversion from integer to double can't always be done without loss of precision. Consequenltly, you can get problems if Weight is an integer type that can hold large values, e.g. a size_t
All 32 bit integers can be converted without problems (aka loss of precision).