mem_fun and mem_fun_ref and many other member function adaptors can make member functions act like orindinary functions. But there is one restriction that the member function that they call must be a const one. I get to know how to use them, but confused and puzzled by the reasons behind it. Why is it designed in this way?
update:
Sorry for the ambiguity. write an example below.
class A
{
...
//void fun(){cout<<"Fun";} This is not const and the compiler would complain
void fun() const {cout<<"Not fun";}
...
}
vector<A> avec;
...
for_each(avec.begin(),avec.end(),mem_fun_ref(&A::fun));
...
There is no such a restriction. These template functions are overloaded for const and non-const member functions.
For example
template<class S, class T>
mem_fun_t<S,T> mem_fun(S (T::*f)());
template <class S, class T>
const_mem_fun_t<S,T> mem_fun(S (T::*f)() const);
Related
My professor gave us this piece of code to study to better understand how class templates work in C++ but I'm confused on what the second line means. I put two asterisks (**) next to the statement I'd like more clarification on.
template<typename T>
Pair<T>::Pair(const T& firstVal, const T& secondVal) //**
{
first = firstVal;
second = secondVal;
}
This is the Pair class template :
template<typename T>
class Pair
{
public:
Pair();
Pair(const T& firstVal, const T& secondVal);
void setFirst(const T& newVal);
void setSecond(const T& newVal);
T getFirst() const;
T getSecond() const;
~Pair(){}
private:
T first, second;
};
What I'm confused about is why she's treating the constructor as a function and defining it as the class has no member functions with the name "Pair" apart from the constructor? I'm sure I'm misunderstanding something about constructors and functions and if someone could help I'd greatly appreciate it, thank you!
The mentioned snippet is an out-of-class definition for a constructor of a class template. In particular, to define a member function(which a constructor also is) of a class template, we have to specify that it is part of a template and so we have to use the full type qualification of the class template.
For instance, say you want to have an out-of-class definition for the member function setFirst, then you would define it as follows:
template<typename T> //parameter clause goes here
void Pair<T>::setFirst(const T& newVal) //full type qualification goes here
{
}
Similarly, if we want to have an out-of-class definition for the constructor then we will do it as follows:
template<typename T>//parameter clause is here
Pair<T>::Pair(const T& firstVal, const T& secondVal)//full type qualification is here
: first(firstVal), second(secondVal)
{
}
Note that a constructor is a special member function.
Well, Pair() and Pair(const T& firstVal, const T& secondVal) are both functions. Constructors are functions that are called when the object is initialised, and you can define and then implement the constructors later, just like any other normal member function.
A non-templated class's constructor implementation would look like this:
myClass::myClass(/* my args ... */) {
// do stuff ...
}
And, if myClass is a templated class, you would have to have type T defined somewhere, and that would be done like so:
template <typename T>
myClass<T>::myClass(/* my args ... */) {
// do stuff ...
}
This lets you also define specific specialisations, say if you want your class's constructor to have specific functionality for when T = int. You would define it using the template!
template<>
myClass<int>::myClass(/* my args ... */) {
// do special integer stuff!
}
I have a BinaryMemoryReader class that has a function defined like this:
template <typename T>
inline void read(T **data) {
*data = (T*)&stream[position];
position += sizeof(T);
}
It handles most of the standard types from a stream in memory.
The custom complex types have read functions of their own, such as:
void AnotherClass::read(BinaryMemoryReader *const reader)
{
reader->read<bool>(&num);
reader->read<short>(&count);
}
What I'd like to is write the code that would, when I write
reader->read<AnotherClass>(&var);
would call the second function. It would mean that AnotherClasss read function would overload the BinaryMemoryReaders read function for that particular type.
It would allow me to write a much more cleaner code.
EDIT:
The general idea is this:
Have a central BinaryMemoryReader class.
Have a generic read function within it to deal with the standard types.
Have the syntax to call it be bmr->read<int>(&intVar);
Have specialized read functions defined in their own classes.
Most importantly, the syntax to call them would be bmr->read<customType>(&customTypeVar);
That way the specific read functions would be associated with their own classes, but would be able to be called from the BinaryMemoryReader.
As I wrote in my comment I would use the following approach:
Have a templated free function
template <typename T>
void read(BinaryMemoryReader& bmr, T& data) {
bmr.read(&data);
}
Specialize that function for each of the types you want to handle
class AnotherClass {
template <typename T>
friend void read(BinaryMemoryReader& bmr, T &data);
bool num;
short count;
};
template <>
void read(BinaryMemoryReader& bmr, AnotherClass &data) {
bmr.read<bool>(&(data.datanum));
bmr.read<short>(&(data.count));
};
Call it like
BinaryMemoryReader bmr;
AnotherType at;
read(bmr,at);
That technique is used for instance with the c++ standard I/O library and overloads provided for the
std::ostream& operator<<(std::ostream&, const T&);
std::istream& operator>>(std::istream&, T&);
functions.
Alternatively you could do that specialization for the BinaryMemoryReader::read() function. But BinaryMemoryReader must be friend of all class specializations.
I am trying to understand a piece of code of C++11.
A class contains 2 functions as shown below:
class abc
{
public:
void integerA(int x);
template<typename typ>
void integerA(typ x);
};
I am unable to understand benefit of declaring 2 same functions. Why not declare only one template function?
Only one benefit I can assume is we know int data type which can be passed to this function. This might be little faster. But for this, do we really need to create a separate function with int data type?
The main reason to do something like this is to specialize void integerA(int x) to do something else. That is, if the programmer provides as input argument an int to member function abc::integerA then because of the C++ rules instead of instantiating the template member function the compiler would pick void integerA(int x) because concrete functions are preferred when possible instead of instantiating a template version.
A more straightforward way to do this would be to specialize the template member function in the following manner:
class abc
{
public:
template<typename typ>
void integerA(typ x);
};
template<typename typ>
void abc::integerA(typ x) {
...
}
template<>
void abc::integerA(int x) {
...
}
LIVE DEMO
Let's consider following classes:
struct InputArgument{};
struct SpecialInputArgument{};
struct MoreSpecialInputArgument{};
struct OutputArgument{};
struct SpecialOutputArgument{};
struct MoreSpecialOutputArgument{};
I need to have a member function that accepts all previous classes as arguments and act on them. To simplify the implementation (don't repeat same code over and over) I made the member function template and dispatched the actual code to non-member functions:
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value>::type DoSomething(T&, const InputArgument&)
{
}
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value>::type DoSomething(const T&, OutputArgument&)
{
}
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value>::type DoSomething(T&, const SpecialInputArgument&)
{
}
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value>::type DoSomething(const T&, SpecialOutputArgument&)
{
}
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value>::type DoSomething(T&, const MoreSpecialInputArgument&)
{
}
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value>::type DoSomething(const T&, MoreSpecialOutputArgument&)
{
}
struct MyGloriuosClass
{
template<typename T>
void DoSomething(T& arg)
{
::DoSomething(myIntMember, arg);
::DoSomething(myFloatMember, arg);
}
int myIntMember = 0;
float myFloatMember = 0.f;
};
And this works perfect:
MyGloriuosClass myGloriuosObject;
InputArgument inputArgument;
SpecialInputArgument specialInputArgument;
MoreSpecialInputArgument moreSpecialInputArgument;
OutputArgument outputArgument;
SpecialOutputArgument specialOutputArgument;
MoreSpecialOutputArgument moreSpecialOutputArgument;
myGloriuosObject.DoSomething(inputArgument);
myGloriuosObject.DoSomething(specialInputArgument);
myGloriuosObject.DoSomething(moreSpecialInputArgument);
myGloriuosObject.DoSomething(outputArgument);
myGloriuosObject.DoSomething(specialOutputArgument);
myGloriuosObject.DoSomething(moreSpecialOutputArgument);
Expect in one case, when the object I use is const:
const MyGloriuosClass myConstGloriousObject = MyGloriuosClass();
myConstGloriousObject.DoSomething(outputArgument);
myConstGloriousObject.DoSomething(specialOutputArgument);
myConstGloriousObject.DoSomething(moreSpecialOutputArgument);
As you can see, all the actual code is done in functions that accept const objects when the argument is of type Output so there is no reason to limit this to only non-const objects or to write my member function twice, once as const and once as non-const. In my ideal world I will deduce if the function is const/non-const based on the type trait std::is_base_of of the argument, but I don't know if this is possible or not.
Is it possible to declare a member function const/non-const based on compile time conditions?
A member function is either const, or non-const member function. There is no third option. Classes can define either a const function, a non-const function, or even both, as you know.
What I suspect that you might be missing is that a const member function can be invoked for a non-const class instance.
So, if your member function does not need to modify any other members of the class instance, just declare your member function as a const function, and it can be invoked for either a const or a non-const class instance.
For example
class A {
public:
void fun(Array a);
void fun(Vector a);
/* Most codes in these two functions are same. */
/* Can certainly be merged into a template function if they were not member functions. */
}
Please note that I hope to have both these two versions of fun() in class A. Thanks.
Even if the class is not templated itself you can write a member function that is templated in the same manner that you would write a templated function that was not a method of a class.
template <class myType >
myType func (myType a) {
/* do something */;
}
Yes it is possible, see this SO question.
Yes it is possible to create template member function like normal function. Just keep the code generic like it can work in both the situations involving vector and other data types.
template <typename T>
void fun(T var) {}