Is there a way to use templates to create a standard constructor of class in your main?
If I have a class:
myclass.h
class myClass
{
private:
float a;
public:
myClass(float _a) {a = _a;}
float getA(){return a;}
~myClass() {}
};
Is there a way to template this in your main like so:
main.cpp
#include "myclass.h"
typedef myClass<5.0> Dummy
int main(int argc, char const *argv[])
{
// EDIT: removed the following typo
// Dummy dummy();
Dummy dummy;
std::cout << dummy.getA() << std::endl;
return 0;
}
Which should output:
> 5.0000000
So that one may define in the main a standard way to construct the instances.
C++17 and Below
Unfortunately C++ does not allow you to use floating point types as non-type template parameters yet. That said, you can fake it by accepting a numerator and denominator as integers and then doing that "math" in the class to get a floating point value. That would look like
template<size_t numerator, size_t denominator = 1> // use a default value so you don't have to specify the denominator for whole values
class myClass
{
private:
float a;
public:
myClass(float _a = static_cast<float>(numerator) / denominator) : a(_a) {}
float getA(){return a;}
~myClass() {}
};
typedef myClass<5> Dummy;
int main(int argc, char const *argv[])
{
Dummy dummy; // notice this isn't Dummy dummy();. That makes a function, not a variable
std::cout << dummy.getA() << std::endl;
return 0;
}
You could also add a default value to numerator if you want to so that you could do
// Pre C++17
myClass<> foo;
//C++17 and later
myClass foo;
C++20
Now that we can use floating point types1 the code can be simplified to:
template<float default_value = 0.0f>
class myClass
{
private:
float a;
public:
myClass(float _a = default_value) : a(_a) {}
float getA(){return a;}
~myClass() {}
};
typedef myClass<5.0f> Dummy;
int main(int argc, char const *argv[])
{
Dummy dummy;
std::cout << dummy.getA() << std::endl;
return 0;
}
1: no compilers actually support this yet, but it is allowed per the standard
Building onto #pptaszni's answer, you could create a "factory factory function":
auto makeMyClassFactory(float value) {
return [=] {
return myClass{value};
};
}
auto const Dummy = makeMyClassFactory(5.0f);
int main(int argc, char const *argv[])
{
auto dummy = Dummy();
std::cout << dummy.getA() << std::endl;
return 0;
}
See it live on Wandbox
You are possibly better off just using a default instance which you make copies of whenever you need a new instance:
#include "myclass.h"
Dummy myClass(5.0);
int main(int argc, char const *argv[])
{
myClass dummy1 = Dummy;
std::cout << dummy1.getA() << std::endl;
myClass dummy2 = Dummy;
std::cout << dummy2.getA() << std::endl;
return 0;
}
Not really, but you can write a factory function (or class if it is more complicated) like this:
myClass createMyClassV5()
{
return myClass(5.0);
}
Unfortunately, you cannot make it a template, because float are not allowed to be template non-type parameters. You could do it with int though.
Related
Does a class template -that takes integer parameter- define multiple classes for different integer inputs?
for ex:
I applied the following code
template<int val>
class MyClass
{
public:
static int var;
};
template<int val> int MyClass<val>::var = val;
int main(int argc, char* argv[])
{
MyClass<5> a;
MyClass<7> b;
MyClass<9> c;
std::cout << a.var << " , " << b.var << " , " << c.var << std::endl;
return 0;
}
Output
5 , 7 , 9
does it mean that a class definition is created for every integer passed as template argument (as the static member variable is different every time) ?
Is there a way to check the generated class definitions? I tried to check map file and assembly code but no luck
Yes, these will be 3 distinct types
You can for instance use C++ Insights to get an idea of the code that the compiler generates from class templates.
#include <iostream>
template<int val>
class MyClass
{
public:
static int var;
};
/* First instantiated from: insights.cpp:14 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class MyClass<5>
{
public:
static int var;
// inline constexpr MyClass() noexcept = default;
};
#endif
/* First instantiated from: insights.cpp:15 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class MyClass<7>
{
public:
static int var;
// inline constexpr MyClass() noexcept = default;
};
#endif
/* First instantiated from: insights.cpp:16 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class MyClass<9>
{
public:
static int var;
// inline constexpr MyClass() noexcept = default;
};
#endiint MyClass<9>::var = 9;
int main(int argc, char ** argv)
{
MyClass<5> a = MyClass<5>();
MyClass<7> b = MyClass<7>();
MyClass<9> c = MyClass<9>();
std::operator<<(std::operator<<(std::cout.operator<<(a.var), " , ").operator<<(b.var), " , ").operator<<(c.var).operator<<(std::endl);
return 0;
}
edit: Altough you see CppInsight is not perfect, as it screwed up the instantiation of the static member variables.
I want to store a function in a class and simply call this function inside a member function. I know that this is possible using function pointers but I want to use std::function for this.
Here is some code that is not working but should demonstrate what I want to do:
double foo(double a, double b){
return a + b;
}
class Test{
private:
std::function<double(double,double)> foo_ ;
public:
Test(foo);
void setFoo(foo) {foo_ = foo;}
double callFoo(double a, double b){return foo_(a,b);}
};
int main(int argc, char const *argv[]) {
Test bar = Test(foo);
bar.callFoo(2,3);
return 0;
}
You almost did it right, but forgot the types in your constructor and setFoo:
#include <functional>
#include <iostream>
double foo(double a, double b) {
return a + b;
}
class Test {
private:
std::function<double(double, double)> foo_;
public:
// note the argument type is std::function<>
Test(const std::function<double(double, double)> & foo) : foo_(foo) {}
// note the argument type is std::function<>
void setFoo(const std::function<double(double, double)>& foo) { foo_ = foo; }
double callFoo(double a, double b) { return foo_(a, b); }
};
int main(int argc, char const *argv[]) {
Test bar = Test(foo);
bar.callFoo(2, 3);
return 0;
}
By the way, it is often beneficial to use a typedef to avoid long and complicated names, for example if you do
typedef std::function<double(double,double)> myFunctionType
you can use myFunctionType everywhere, which is easier to read (provided you invent a better name than "myFunctionType") and more tidy.
I'm looking for a bit of syntactic sugar that I'm not sure exists. It's hard to describe, so I'll provide an example:
#include <iostream>
using namespace std; // haters gonna hate
union MyUnion
{
float f;
unsigned int i;
// more types
};
unsigned int someFunction(MyUnion m)
{
return m.i;
}
int main()
{
unsigned int i = 10;
float f = 10.0;
// this is the syntactic sugar I'm looking to emulate
cout << someFunction(i) << endl; // automagically initializes unsigned int member
cout << someFunction(f) << endl; // automagically initializes float member
return 0;
}
I'm aware I can just define a bunch of overloads of my function, declare the union on the stack, initialize it, like such:
unsigned int someFunction(unsigned int i)
{
return i; // this is the shortcut case
}
unsigned int someFunction(float f)
{
MyUnion m = {f};
return m.i;
}
// more overloads for more types
But I'm hoping there's a better way. Is there?
You can give the union some constructors:
union Jack
{
int a;
float f;
Jack(int a_) : a(a_) { }
Jack(float f_) : f(f_) { }
};
Jack pot(1);
Jack son(1.);
int main()
{
someFunction(Jack(100));
someFunction(100); // same, implicit conversion
}
I've always wondered is there a way to have a class member without using getters that can only be modified by it's class?
What I'm thinking of is something like this.
class A
{
public:
crazyconst int x;
void doStuff()
{
// Gettin' stuff done
x = someValue; // OK
}
};
int main(int argc, char** argv)
{
A a;
a.x = 4; // ERROR
}
So it's visible, but read-only for everyone beside its class.
Your class could have a public const reference to a private, non-const data member.
Edit: However, I should point out that doing this would prevent you from using the compiler-generated copy constructor and copy assignment operator.
The answer is no you can't do this without a getter of some sort. However, you can make the getter reusable and you can make the simple syntax of a field work (mostly), without parentheses.
(C++11 required)
template<typename Friend, typename FieldType>
class crazyconst
{
FieldType value;
friend Friend;
FieldType& operator=(const FieldType& newValue) { return value = newValue; }
public:
operator FieldType(void) const { return value; }
FieldType operator()(void) const { return value; }
};
class A
{
public:
crazyconst<A, int> x;
void doStuff()
{
// Gettin' stuff done
x = 5; // OK
}
};
int main(int argc, char** argv)
{
A a;
int b = a.x;
int c = a.x(); // also works
}
C++03 version: http://ideone.com/8T1Po
But beware, this will compile but not work as expected:
const int& the_x = a.x;
a.doStuff();
std::cout << the_x;
OTOH, this should be fine:
const auto& ref_x = a.x;
a.doStuff();
std::cout << ref_x;
I would like someone to explain me the "name::name" syntax and how it is used on C++ programming. I have been looking through but I don't get it yet. Thanks for help.
Here is context code:
void UsbProSender::SendMessageHeader(byte label, int size) const {
Serial.write(0x7E);
Serial.write(label);
Serial.write(size);
Serial.write(size >> 8);
}
:: is the scope resolution operator.
std::cout is the name cout in the namespace std.
std::vector::push_back is the push_back method of std::vector.
In your code example:
void UsbProSender::SendMessageHeader(byte label, int size) const {
Serial.write(0x7E);
Serial.write(label);
Serial.write(size);
Serial.write(size >> 8);
}
UsbProSender::SendMessageHeader is providing the definition for the SendMessageHeader method of the UsbProSender class.
Another (more complete) example:
class Bar {
int foo(int i); // forward declaration
};
// the definition
int Bar::foo(int i) {
return i;
}
It is operator for scope resolution.
Consider that code
class A { public: void f(){} };
class B { public: void f(){} };
class C : public A, public B {};
int main(int argc, char *argv[])
{
C c;
// c.f(); // ambiguous: which one of two f() is called?
c.A::f(); // OK
c.B::f(); // OK
return 0;
}