What does this "<>" mean inside a template class function? - c++

There is a code like this.
const std::string DeviceTypeStrings[] ={ "A", "B", "C", "D", "E" };
enum DeviceTypes { A = 0, B, C, D, E };
template <DeviceTypes T> class DeviceType;
template <DeviceTypes T> std::ostream& operator<< (std::ostream& output, const DeviceType<T>& dev);
template <DeviceTypes T> class DeviceType {
public:
static const int value = T;
static const std::string string;
friend std::ostream & operator<< <>(std::ostream & output, const DeviceType<T> & deviceType );
};
template <DeviceTypes T> const std::string DeviceType<T>::string = DeviceTypeStrings[T];
template <DeviceTypes T> std::ostream & operator<< (std::ostream & output, const DeviceType<T> & deviceType ){
if ( DeviceType<T>::string.find(' ') != std::string::npos ){
return output << "\"" << DeviceType<T>::string << "\"";
} else {
return output << DeviceType<T>::string;
}
}
int main () {
DeviceType<A> myType;
std::cout << myType << std::endl;
return 0;
}
Note there is a "<>" after the operator<< inside class DeviceType, what does "<>" mean? If you could, why does it has to be there?

It simply means that the friend declaration refers to a particular specialization of function template operator << (declared previously), not to some yet undeclared ordinary non-template function operator <<.
Which specialization this friend declaration refers to is determined by the argument deduction mechanism, i.e. the actual template arguments are implicitly derived from the parameter types used in friend declaration. For this reason there's no need to specify template arguments in <> explicitly, but an empty pair of <> is still required.
In other words, the author of the code could've stated explicitly
friend std::ostream & operator<< <T>(std::ostream & output,
const DeviceType<T> & deviceType );
(note the explicit T in <T>). However, since the compiler can figure it out by itself (derive it from the type of the second argument), it is perefectly possible to put just an empty pair of <> there.
Now, if the code just said
friend std::ostream & operator<<(std::ostream & output,
const DeviceType<T> & deviceType );
(i.e. no <> at all), it would befriend an ordinary (non-template) function operator <<, which is not what the author wanted.
Overload resolution feature that works in this friend declaration can be illustrated without any friend declarations by the following simple example
void foo(int);
template <typename T> void foo(T);
int main() {
foo(42); // calls non-template function
foo<int>(42); // calls template function, explicit template argument given
foo<>(42); // calls template function, template argument deduced by compiler
}
When you want to tell the compiler that you specifically want to refer to a template version of the function, you have to include triangular brackets into the reference, even if there's nothing between them.

The compiler checks for < after operator<< if it's a friend function of a template class. It's considered as the template argument list.

It is same like at this link.
See the "Template specialization" chapter.
// template specialization
#include <iostream>
using namespace std;
// class template:
template <class T>
class mycontainer {
T element;
public:
mycontainer (T arg) {element=arg;}
T increase () {return ++element;}
};
// class template specialization:
template <>
class mycontainer <char> {
char element;
public:
mycontainer (char arg) {element=arg;}
char uppercase ()
{
if ((element>='a')&&(element<='z'))
element+='A'-'a';
return element;
}
};
int main () {
mycontainer<int> myint (7);
mycontainer<char> mychar ('j');
cout << myint.increase() << endl;
cout << mychar.uppercase() << endl;
return 0;
}
It's just how you refer to already defined template object (or function).

Related

const struct object access member functions (and an operator overloading question)

I tried to overload the << operator for my custom struct, but encountered error C2662, code as follows:
struct HP{
int max_hp;
int hp;
HP(int max_hp){
this->max_hp=max_hp;
this->hp=max_hp;
}
// this const declarative doesn't support const HP& obj argument
const string repr(){
stringstream hp_stats;
hp_stats << this->hp << "/" << this->max_hp;
return hp_stats.str();
}
// This is fine with const HP& obj argument
const string repr(){
stringstream hp_stats;
hp_stats << this->hp << "/" << this->max_hp;
return hp_stats.str();
}
};
// would cause error C2662
ostream& operator<<(ostream& out, const HP& obj){
out<<obj.repr();
return out;
}
I've found that this is because the implicitly access of this pointer, and const attempts to convert *this into const *this and thus fails. But as I changed from const string repr() to string repr() const, it magically worked and compiled successfully.
What's the difference between a const T func(){} and T func() const, which makes a const struct object invoking feasible?
I read it on cppreference.com, but still unsure why << overloading has to be declared outside a class scope.
Suppose I have repr() member function for struct HP, struct Shield, etc. I tried to make the << overloading a template function, but it turns that I am overloading << at global scope. Can I specify the T I am about to apply, OR apply the overloading across several classes with same member function, WITHOUT classes defined under one base class?
// complier thinks such overloading is global on <<
template <typename T>
ostream& operator<<(ostream& out, const T& obj){
out<<obj.repr();
return out;
}
const T func() {} means that the return type is const T and the function might mutate the object. Whereas, T func() const {} means that the return type is non-const but the object is unaltered (const). You can also have both or neither const.
It doesn't have to be declared outside the class, it can be declared inside as a friend (non-member) function. That works here as well. However, for a member function: since operator<<()'s first parameter is ostream&, you could only declare it in ostream and not HP, which won't work. Remember, member operators are like *this as the first argument of non-member operators.
Yes, you can do this. The easiest is to delegate to a common print function; the more elegant way is to use std::enable_if, e.g.:
template <typename T>
std::enable_if_v<std::is_same_v<T, HP> || std::is_same_v<t, Shield>, ostream&>
operator<<(ostream& out, const T& obj)
{
out<<obj.repr();
return out;
}
You can also write the conditions as a template and then re-use it:
template<typename T>
static constexpr bool is_printable_v = std::is_same_v<T, HP> || std::is_same_v<T, Shield>;
template <typename T>
std::enable_if_v<is_printable_v<T>>, ostream&>
operator<<(ostream& out, const T& obj) { ... }

How to explicity call a templated overload of operator <<?

Consider the following example code for overloading the operator<< for a class A:
#include <iostream>
class A {
template <typename T>
friend A &operator<<(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
friend A &operator<<(A &a, const std::string &t)
{
return operator<<<std::string>(a, t + "x");
}
};
My intention is that the second operator explicitly calls the first one.
However, in g++ 7.4 this fails with
In function 'A& operator<<(A&, const string&)':
error: 'operator<<' not defined
return operator<<<std::string>(a, t + "x");
^~
error: expected primary-expression before '>' token
return operator<<<std::string>(a, t + "x");
^
I however do not see why this should not compile.
Here is the code in godbolt.
In-class friend functions are not exposed to any scope. Friend injection used to be a thing (before ADL was invented), but now there is no way to call them except with ADL unless you declare them beforehand. In this case, a workaround is to declare the template function outside the class beforehand.
class A;
template <typename T>
A &operator<<(A &a, const T &t);
Call a function instead of calling an operator.
#include <iostream>
class A {
template <typename T>
static A &print(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
template <typename T>
friend A &operator<<(A &a, const T &t)
{
return print(a, t);
}
friend A &operator<<(A &a, const std::string &t)
{
return print(a, t + "x");
}
};
You seem to wish to specialize your template function, but you're not doing it quite right. It should look more like this:
template <> friend A& operator<< <std::string>(A &a, const std::string &t)
{
// Print in here some how. It's not exactly clear to me how you intend to
// do this, as doing something like a << t will create infinite recursion
// finally, return a
return a;
}
Your other option is to switch the order of the functions, creating the template function after you create your first function:
friend A &operator<<(A &a, const std::string &t)
{
// Again, still not sure what you want to do here
// I just want to stress again though, don't do something
// like a << t, or operator<<(a,t)
// That will crash hard and fast, as there is no way to resolve
// it. It will create infinite recursion
return a;
}
template <typename T>
friend A &operator<<(A &a, const T &t)
{
std::cout << t << std::endl;
return a;
}
My intention is that the second operator explicitly calls the first one.
So, first, you will need to actually need the first option in that case.
Second, to do this, you will need to choose a type for t. You would do it like this:
operator<< <SomeType>(a,t);
Keep in mind, t will need to be implicitly converted to SomeType. Else, SomeType needs to be created by calling its constructor:
operator<< <SomeType>(a,SomeType(/* parameters to construct a SomeType ... */));
Note: Doing something like operator<< <SomeType>(a,t + "x") will always become infinitely recursive, and ultimately crash. This is because t + "x" is always an std::string. That means the compiler will always call this overload of the function infinitely, until it finally crashes from a stack overflow. So don't do that.

Storing member function pointer from arbitrary class as class instance variable

There are a few questions on SO that address passing function pointers as parameters/arguments (here, here, here, etc.). In fact, I asked a related question the other day. However, this question is a little different.
My problem is that I am writing a class that I want to be extremely flexible.
What I have now works for non-member functions. It is posted below
template <typename T>
class MyClass
{
private:
typedef double (*firstFunctionPtr) (const T &var);
typedef bool (*secondFunctionPtr)(const T &var);
// Function pointers as member variables
firstFunctionPtr _firstFunc;
secondFunctionPtr _secondFunc;
public:
inline MyClass(firstFunctionPtr firstFunc,
secondFunctionPtr secondFunc);
};
template<typename T>
MyClass<T>::MyClass(firstFunctionPtr firstFunc, secondFunctionPtr secondFunc) :
_firstFunc(firstFunc),
_secondFunc(secondFunc),
{}
However, this falls apart when I need to initialize with a pointer to a member function of some other, arbitrary, class, which, unfortunately for me, happens to be a common use case for my purposes.
This answer suggests that
In a proper C++ interface you might want to have a look at having your function take templated argument for function objects to use arbitrary class types.
However, I have not been able to make this compile. I've tried templating my typedefs (using the C++11 aliasing approach), and I've tried adding a second template parameter to the class to handle the calling class of those member functions, but neither approach has worked.
This Q/A seems to be getting towards what I'm trying to do, but I can't make heads or tails of it.
Can someone please explain how I might modify my class to handle arbitrary member functions pointers being passed in?
Furthermore, is it possible to make it so that it can handle either arbitrary member functions or non-member functions?
Lastly, is it possible to do this with templates?
For the record, I'm trying to avoid using the functional header, but it may be a fool's errand not to use it.
If you want MyClass to be a template that can hold both free function
pointers of types:
double (*)(const T &var);
bool (*)(const T &var);
for some parameter type T, or alternatively member-function
pointers of types:
double (C::*)(const T &var);
bool (C::*)(const T &var);
for some parameter types C and T then, MyClass must be parameterized
by both T and C and you require two specializations:
Where C is some non-class type
Where C is any class type
In case (1), the non-class type C cannot possibly have member functions,
so that one will implement the free-function pointer specialization.
In case (2), the class C could be one that has member functions, so that one
will implement the member-function pointer specialization.
The obvious choice for a non-class type C is void. So we can make C
default to void:
Primary template
template<typename T, typename C = void>
struct MyClass;
So that:
MyClass<T>
will be the free function pointer specialization for T, and:
MyClass<T,C>
for any C other than void, will be the member-function pointer specialization.
As you may know you can use std::enable_if
and SFINAE to make the compiler
chose one specialization of a class template or another, depending on whether one
of its template parameters U satisfies some compiletime test. You could take
that approach here, but another one is available that does not require that apparatus:
Starting with the primary template, we would just like to have:
Free function specialization
template<typename T>
struct MyClass<T>
{
... for free function pointers ...
};
and:
Member function specialization
template<typename T, typename C>
struct MyClass<T,C>
{
... for member function pointers ...
};
But we can't have just that, because the member function "specialization" has exactly
the same template parameters as the primary template. Which means it isn't
a specialization, and the compiler won't allow it.
You can easily remove that problem, however, simply by giving the primary
template one more defaulting template parameter that it doesn't need, but whose
presence allows both those specializations to stand.
New primary template
template <typename T, typename C = void, typename Default = void>
struct MyClass;
So here is an illustrative solution:
// Primary template
template <typename T, typename C = void, typename Default = void>
struct MyClass;
// Free function specialization
template <typename T>
struct MyClass<T>
{
using firstFunctor_t = double(*)(T const &);
using secondFunctor_t = bool(*)(T const &);
MyClass(firstFunctor_t firstFunc, secondFunctor_t secondFunc)
: _firstFunc(firstFunc),
_secondFunc(secondFunc)
{}
double callFirst(T const & var) {
return _firstFunc(var);
}
bool callSecond(T const & var) {
return _secondFunc(var);
}
private:
firstFunctor_t _firstFunc;
secondFunctor_t _secondFunc;
};
// Member function specialization
template <typename T, typename C>
struct MyClass<T,C>
{
using firstFunctor_t = double(C::*)(T const &);
using secondFunctor_t = bool(C::*)(T const &) const;
MyClass(firstFunctor_t firstFunc, secondFunctor_t secondFunc)
: _firstFunc(firstFunc),
_secondFunc(secondFunc)
{}
double callFirst(C & obj, T const & var) {
return (obj.*_firstFunc)(var);
}
double callFirst(C const & obj, T const & var) {
auto & o = const_cast<C&>(obj);
return (o.*_firstFunc)(var);
}
bool callSecond(C & obj, T const & var) {
return (obj.*_secondFunc)(var);
}
bool callSecond(C const & obj, T const & var) {
auto & o = const_cast<C&>(obj);
return (o.*_secondFunc)(var);
}
private:
firstFunctor_t _firstFunc;
secondFunctor_t _secondFunc;
};
In the member function specialization, notice a couple of points that you might
not have considered:-
I decided that the second member function I want to store shall be a
const member function. It's more than likely that a member function of C
that take a T const & argument and returns bool will be a const member
function, isn't it? And if so, then that const-ness has to be part of
the member-function type definition that I use in the specialization:
using secondFunctor_t = bool(C::*)(T const &) const;
or attempts to instantiate the specialization with any bool (C::*)(T const &) const
will fail to compile.
Also, I have provided two overloads for each of MyClass<T,C>::callFirst
and MyClass<T,C>::callSecond, one with arguments:
C & obj, T const & var
and another with arguments:
C const & obj, T const & var
Without the second, attempts to call either MyClass<T,C>::callFirst
or MyClass<T,C>::callSecond with an obj that is const will fail to
compile.
For program to demo this solution you can append:
#include <iostream>
#include <string>
double foo(std::string const & s)
{
return std::stod(s);
}
bool bar(std::string const & s)
{
return s.size() > 0;
}
struct SomeClass
{
SomeClass(){};
double foo(std::string const & s) {
return ::foo(s);
}
bool bar(std::string const & s) const {
return ::bar(s);
}
};
int main()
{
MyClass<std::string> my0{foo,bar};
std::cout << std::boolalpha;
std::cout << my0.callFirst("1.11") << std::endl;
std::cout << my0.callSecond("Hello World") << std::endl;
MyClass<std::string,SomeClass> my1{&SomeClass::foo,&SomeClass::bar};
SomeClass thing;
std::cout << my1.callFirst(thing,"2.22") << std::endl;
std::cout << my1.callSecond(thing,"Hello World") << std::endl;
SomeClass const constThing;
std::cout << my1.callFirst(constThing,"3.33") << std::endl;
std::cout << my1.callSecond(constThing,"Hello World") << std::endl;
return 0;
}
See it live
You said that you want this template to be "extremely flexible". The
illustrated solution is fitted to your example, but you might be
interested in know that it isn't nearly as flexible as you could get.
For both free functions and member functions, with additional variadic template
parameters, your template could store and call [member] functions with
arbitary return types and arbitary numbers of arguments of arbitrary types.
See this question and
answer.
I will sugest to create a helper object which will store the type you want to work with:
template <typename RETURN, typename TYPE, typename CLASS>
struct function_pointer
{ using type_t = RETURN (CLASS::*)(const TYPE &); };
template <typename RETURN, typename TYPE>
struct function_pointer<RETURN, TYPE, std::nullptr_t>
{ using type_t = RETURN (*)(const TYPE &); };
This type will create a member-function-pointer if a class is provided as third parameter and a function-pointer otherwise. Now, we can use this helper in MyClass:
template <typename T, typename CLASS = std::nullptr_t>
class MyClass
{
using firstFunctionPtr = typename function_pointer<double, T, CLASS>::type_t;
using secondFunctionPtr = typename function_pointer<bool, T, CLASS>::type_t;
// Function pointers as member variables
firstFunctionPtr _firstFunc;
secondFunctionPtr _secondFunc;
public:
inline MyClass(firstFunctionPtr firstFunc, secondFunctionPtr secondFunc) :
_firstFunc(firstFunc),
_secondFunc(secondFunc)
{}
void call_first(CLASS &c, const T&v) { (c.*_firstFunc)(v); }
void call_second(CLASS &c, const T&v) { (c.*_secondFunc)(v); }
void call_first(const T&v) { (_firstFunc)(v); }
void call_second(const T&v) { (_secondFunc)(v); }
};
I've added call_* functions just to show a use case, which will be as below:
// Some class with the expected function signatures
struct S1
{
int i = 0;
double d(const int &) { std::cout << i << ' ' << __PRETTY_FUNCTION__ << '\n'; return{}; }
bool b(const int &) { std::cout << i << ' ' << __PRETTY_FUNCTION__ << '\n'; return{}; }
};
// Another class with the expected function signatures
struct S2
{
double d(const int &) { std::cout << __PRETTY_FUNCTION__ << '\n'; return{}; }
bool b(const int &) { std::cout << __PRETTY_FUNCTION__ << '\n'; return{}; }
};
// Free function with which could have the expected function signature
template <typename R>
R f(const int &) { std::cout << __PRETTY_FUNCTION__ << '\n'; return{}; }
Using MyClass with an arbitrary class (S1):
S1 a{1}, b{2};
S2 c, d;
MyClass<int, S1> MCiS1(&S1::d, &S1::b);
MCiS1.call_first(a, 111); // Prints -> 1 double S1::d(const int&)
MCiS1.call_second(b, 222); // Prints -> 2 bool S1::b(const int&)
MCiS1.call_first(c, 111); // Error decltype(c) is not S1.
MCiS1.call_second(d, 222); // Error decltype(d) is not S1.
Using MyClass with a different class (S2):
MyClass<int, S2> MCiS2(&S2::d, &S2::b);
MCiS2.call_first(c, 111); // Prints -> double S2::d(const int&)
MCiS2.call_second(d, 222); // Prints -> bool S2::b(const int&)
MCiS2.call_first(a, 111); // Error decltype(c) is not S2.
MCiS2.call_second(b, 222); // Error decltype(d) is not S2.
Using MyClass with non-member functions:
MyClass<int> MCi(f<double>, f<bool>);
MCi.call_first(111); // Prints -> R f(const int&) [with R = double]
MCi.call_second(222); // Prints -> R f(const int&) [with R = bool]
Check the live demo Here.
All you need to do is bind the object instance for the member function pointer as a first argument.
struct foo {
float bar1(const type &var);
bool bar2(const type &var);
};
foo my_foo;
auto f1 = std::bind(&foo::bar1, my_foo, _1);
auto f2 = std::bind(&foo::bar2, my_foo, _1);
MyClass<type> my_obj(f1, f2);

How to implement a default operator<<(ostream&, T) for type without this operator?

Since std::to_string is added to c++11, I started implementing to_string instead of the more traditional operator<<(ostream&, T). I need to link the two together in order to incorporate libraries that rely on operator<<(ostream&, T). I want to be able to express that if T has operator<<(ostream&, T), use it; otherwise, use std::to_string. I am prototyping a more limited version that enables operator<< for all enum classes.
enum class MyEnum { A, B, C };
// plain version works
//std::ostream& operator<<(std::ostream& out, const MyEnum& t) {
// return (out << to_string(t));
//}
// templated version not working
template<typename T,
typename std::enable_if<std::is_enum<T>::value>::type
>
std::ostream& operator<<(std::ostream& out, const T& t) {
return (out << to_string(t));
}
Compiler says error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'MyEnum')
cout << v << endl;
Questions:
Why is the template function not found by the compiler?
Is there a way to implement the general solution?
The following will work if there exists a std::to_string that accepts an argument of type const MyEnum (which doesn't exist according to clang-703.0.31).
#include <iostream>
#include <type_traits>
enum class MyEnum { A, B, C };
template<typename T>
typename std::enable_if<std::is_enum<T>::value, std::ostream &>::type
operator<<(std::ostream& out, const T& t) {
return (out << std::to_string(t));
}
int main() {
MyEnum a;
std::cout << a << std::endl;
}
According to the docs, there are two ways of using std::enable_if, one of which is to make the return type of a function only valid if T is an enum type (in your case). This is what this code shows. If std::is_enum<T>::value is true, then std::enable_if<std::is_enum<T>::value, std::ostream &>::type results in std::ostream & and is not defined (which makes the compiler yell at you) otherwise.
You could probably write something like my::to_string which would try to convert to a string user-defined types as well:
namespace my {
template<typename T>
typename std::enable_if<! std::is_void<T>{} && std::is_fundamental<T>{}, std::string>::type
to_string(T t) {
return std::to_string(t);
}
std::string to_string(std::nullptr_t) = delete;
std::string to_string(MyEnum a) {
return "This is an enum";
}
}
Then, you can use my::to_string instead of std::to_string in your operator<<:
return (out << my::to_string(t));
EDIT: using my::to_string now results in a compilation error when it's argument is void or std::nullptr_t.
Why your code didn't work
Look at the example in the docs:
// 2. the second template argument is only valid if T is an integral type:
template < class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even (T i) {return !bool(i%2);}
As you can see, the second template argument is written with class = /* enable_if stuff */, but in your code you do simply template< typename T, /* enable_if stuff */ >. So, if you follow the docs, you'll get the correct result - the compiler will say it couldn't find a specialization of std::to_string that accepted an enum as a parameter.

C++ wrapper class for iostream, use stream modifiers like std::endl with operator<< [duplicate]

This question already has answers here:
std::endl is of unknown type when overloading operator<<
(6 answers)
Closed 10 years ago.
I'm currently writing a wrapper for an std::stringstream and i want to forward all the operator<< calls through my class to the std::stringstream. This works just fine now
(thanks to this question: wrapper class for STL stream: forward operator<< calls), but there is still one issue with it.
Let's say I have the following code:
class StreamWrapper {
private:
std::stringstream buffer;
public:
template<typename T>
void write(T &t);
template<typename T>
friend StreamWrapper& operator<<(StreamWrapper& o, T const& t);
// other stuff ...
};
template<typename T>
StreamWrapper& operator<<(StreamWrapper& o, T const& t) {
o.write(t);
return o;
}
template<typename T>
void StreamWrapper::write(T& t) {
// other stuff ...
buffer << t;
// other stuff ...
}
If I now do this:
StreamWrapper wrapper;
wrapper << "text" << 15 << "stuff";
This works just fine. But if I want to use the stream modifiers like std::endl, which is a function according to http://www.cplusplus.com/reference/ios/endl, I simply doesn't compile.
StreamWrapper wrapper;
wrapper << "text" << 15 << "stuff" << std::endl;
Why? How can I forward the stream modifiers too?
See this answer.
You'll want
typedef std::ostream& (*STRFUNC)(std::ostream&);
StreamWrapper& operator<<(STRFUNC func) // as a member, othewise you need the additional StreamWrappe& argument first
{
this->write(func);
return *this;
}
You seem to be doing a bit of extra work. I normally use:
class StreamWrapper
{
// ...
public:
template <typename T>
StreamWrapper& operator<<( T const& obj )
{
// ...
}
};
With a modern compiler, this should work for all concrete
types. The problem is that manipulators are template functions,
so the compiler is unable to do template argument type
deduction. The solution is to provide non-template overloads
for the types of the manipulators:
StreamWrapper& operator<<( std::ostream& (*pf)( std::ostream& ) )
{
// For manipulators...
}
StreamWrapper& operator<<( std::basic_ios<char>& (*pf)( std::basic_ios<char>& )
{
// For manipulators...
}
Type deduction will fail for the manipulators, but the compiler
will pick up these for function overload resolution.
(Note that you might need even more, for things like std::setw(int).)