friend template function of template class - c++

I have the following simplified code:
template <class T>
class A
{
public:
template <class U>
static U foo(T* p)
{
p;
return U();
}
};
class B
{
/*template <class T>
template <class U>
friend U A<T>::foo<U>(T*);*/
friend B A<B>::foo<B>(B*);
B()
{}
public:
};
...
A<B>::foo<B>(nullptr);
And it works quite well. But the things that I've not managed to do are commented:
/*template <class T>
template <class U>
friend U A<T>::foo<U>(T*);*/
I don't know what the syntax I should use to make it works. So I need to generalize my friend declaration to all possible types. I've tried quite a few variants of syntax but had no success. Could some one point me out what should I write instead of my commented code to make it works?
Thanks!

What you're looking for is
template <class T>
template <class U>
friend U A<T>::foo(T*);
The following works on IdeOne.com
#include <iostream>
template <class T>
class A
{
public:
template <class U>
static U foo(T* p)
{
p;
return U();
}
};
class B
{
template <class T>
template <class U>
friend U A<T>::foo(T*);
B() {}
public:
void hello() const
{
std::cout << "I'm a B!" << std::endl;
}
};
int main(int, char*[])
{
A<B>::foo<B>(NULL).hello();
}

I will agree with the othe commenters, friends and templates simply don't mix, at least not in any consistent way with across a range of compilers. The standard probably states exactly what should work, though that will likely not help you. Sad but true.
Friend is often not a good idea anyhow, it might be better to consider how to write the code without friendship, or use the "poor man's friend" of a public method with a comment indicating it is not for general use.

Related

What template<typename> template <typename> does?

Recently I stumbled upon such piece of code:
template <typename Ta> template <typename Tb>
void SomeClass<Ta>::Function() {}
There is template function, but it has strange syntax, which I don't really understand. What does it do? Is it anwhere near template<template<typename Ta>>?
I have never met such syntax, and I am confused.
Sometimes all it needs is a complete example:
template <typename Ta>
struct SomeClass {
template <typename Tb>
void Function();
};
template <typename Ta> template <typename Tb>
void SomeClass<Ta>::Function() {}
int main() {
SomeClass<int> sc;
sc.Function<double>();
}
It is a definition of a method template of a class template.
Sometimes You need compatibility with compatible objects while writing templates. For example int and double are compatible with each other. But if you have a template class objects lets say Something<int> and Something<double> and you try to assign them it will not work. You do this especially while writing copy or move assignment operators or constructors. Let suppose we have an a class template Something.
template <typename T>
class Something {
public:
Something();
Something(const Something& obj) : data(obj.data)
{
};
private:
T data;
};
int main(){
Something<int> number;
Something<double> double_number;
Something<double> newObj(number);
}
if you try to do this, it will not compile.
To make it compile you make template of your copy constructor as in this case. To make it compile you have to something like this.
template <typename T>
class Something {
public:
Something();
template<typename E>
Something(const Something<E>& obj);
T get_data() const{
return data;
}
private:
T data;
};
template<typename T>
template <typename E>
Something<T>::Something(const Something<E>& src): data(src.get_data()){
}
int main(){
Something<int> number;
Something<double> double_number;
Something<double> newObj(number);
}
Note that we are calling the public method to assign data to this object because Something<int> and Something<double> both are of different types.

How to make base class's operators visible with variadic number of base classes (please see code below)?

What is the best way to expose operators from base class like the following code is trying to do. I suppose with one or two base classes we'd use using syntax, but with a variadic number of base classes, is something like using Base<Ts>::operator=...; possible?
template <typename T, typename Derived>
class varU
{
protected:
varU() = default;
Derived& operator=(T val)
{
static_cast<Derived*>(this)->set(val);
return *static_cast<Derived*>(this);
}
};
template <typename ...Ts>
class var : public varU<Ts, var<Ts...>>...
{
// using varU<Ts, var<Ts...>>::operator=...; // Something like this?
private:
template <typename T>
void set(const T& v)
{
}
};
EDIT:
Seems like using Base<Ts>::operator=... is indeed the correct syntax which I was looking for in C++17. I was using the wrong standard version and expecting C++17. Since this was my guess, I didn't dig deep.
I'm not exactly sure, what you want to achieve with your code, so perhaps you want to go a bit more into detail in your question.
But regarding your question in the code-comment, the answer is yes, it's possible in C++17.
If you actually want to use your operators, you also have to declare the varU class a friend of var:
The following compiles on gcc and clang:
template <typename T, typename Derived>
class varU
{
protected:
varU() = default;
Derived& operator=(T val)
{
static_cast<Derived*>(this)->set(val);
return *static_cast<Derived*>(this);
}
};
template <typename ...Ts>
class var : public varU<Ts, var<Ts...>>...
{
template <typename T, typename Derived>
friend class varU;
public:
using varU<Ts, var<Ts...>>::operator=...; // Something like this?
private:
template <typename T>
void set(const T& v)
{
}
};
int main() {
var<int, float> x;
x = 5;
x = 5.f;
return 0;
}
See live code here.

function implementation with enable_if outside of class definition

So basically, I have a very basic generic class for now, currently testing the type_traits header. I am currently trying to make a function to work with certain types i.e arithmetic ones for now.
#include <type_traits>
template <typename T> class Test {
public:
template <typename U = T>
typename std::enable_if<std::is_arithmetic<U>::value>::type print();
};
The function works perfectly and for arithmetic types only.
But I like to keep my classes tidy and only have them have prototypes, while the function implementations are outside of the class.
With standard templates i.e
void test();
template <typename T> void Test<T>::test() {}
It is simple and I know how to, but I have no clue how to declare the implementation outside of the class with "std::enable_if" and every attempt I have made, during compilation says that that the prototype does not match any in the class.
I have managed to find a similar question here but the class there is standard and not generic.
PS. I am using MinGW-w64 with -std=c++17
You need one set of template parameters for the class template and one separate set of template parameters for the member function template. You need to repeat the entire complicated return type, since it's part of the function template signature. And note you cannot repeat the default argument =T, or the compiler will think you're trying to define it twice (without checking whether or not the new definition is identical).
template <typename T> template <typename U>
typename std::enable_if<std::is_arithmetic<U>::value>::type
Test<T>::print()
{
// Implementation here.
}
By the way, you're using the "long way" of writing the type, as was needed in C++11. But C++14 introduced a std::enable_if_t shortcut, and C++17 introduced a std::is_arithmetic_v shortcut. So if you're using C++17, you can also write the type
typename std::enable_if<std::is_arithmetic<U>::value>::type
as just
std::enable_if_t<std::is_arithmetic_v<U>>
If you put the enable_if in the default template parameter, which is imo nicer anyway, the out-of-class definition becomes a bit easier:
template<typename T>
struct Test
{
template <typename S = T
, typename = typename std::enable_if<std::is_arithmetic<S>::value>::type >
void print();
};
template<typename T>
template<typename S, typename>
void Test<T>::print()
{
//some code
}
You can try with
template <typename T>
template <typename U>
std::enable_if_t<std::is_arithmetic<U>::value> Test<T>::print()
{ /* do something */ }
The following is a full working example
#include <iostream>
#include <type_traits>
template <typename T> class Test
{
public:
template <typename U = T>
std::enable_if_t<std::is_arithmetic<U>::value> print();
};
template <typename T>
template <typename U>
std::enable_if_t<std::is_arithmetic<U>::value> Test<T>::print()
{ std::cout << "test!" << std::endl; }
int main ()
{
Test<int> ti;
Test<void> tv;
ti.print(); // compile
//tv.print(); // compilation error
}
Off Topic 1
Observe that your solution can be hijacked in this way
Test<void>{}.print<int>();
To avoid this problem you could impose that T is equal to U,
template <typename T> class Test
{
public:
template <typename U = T>
std::enable_if_t< std::is_arithmetic<U>::value
&& std::is_same<T, U>::value> print()
{ }
};
Off Topic 2
As you can see, you have to repeat the SFINAE part (std::enable_if_t, std::is_arithmetic and std::is_same).
Taking in count that you have to repeat the implementation in an header, I don't think (IMHO) that to write the implementation of template classes outside the body of the class is a great idea.
Since you haven't posted what you attempted I can't tell you where you went wrong. But this is how you would implement the member function outside the class definition (although it still needs to be implemented in the header, so I don't think this is worth the trouble)
template <typename T> class Test {
public:
template <typename U = T>
typename std::enable_if<std::is_arithmetic<U>::value>::type print();
};
template <typename T> // class template parameter
template <typename U> // function template parameter
inline typename std::enable_if<std::is_arithmetic<U>::value>::type Test<T>::print()
{
}
Live demo
template<typename T>
struct test
{
template<typename U = T>
typename std::enable_if<std::is_arithmetic<U>::value>::type print();
};
template<typename T> template<typename U>
typename std::enable_if<std::is_arithmetic<U>::value>::type test<T>::print()
{
}
void foo()
{
test<int> t;
t.print();
test<void*> u;
u.print();
}
If you need an extra template parameter U, as the other answers explained the right syntax is
template<typename T>
struct test
{
template<typename U>
... a_method(...);
};
template<typename T>
template<typename U>
... test<T>::a_method(...)
{
...
}
However in your peculiar case, if you only need to check some properties of the T type this is really an extra complication. Introduction of the U type is "artificial" and is only here because of the SFINAE
IMHO, it is much more elegant and simpler to use if constexpr
#include <iostream>
#include <type_traits>
template <typename T>
class Test
{
public:
void print();
};
template <typename T>
void Test<T>::print()
{
if constexpr (std::is_arithmetic_v<T>)
{
std::cout << "\nOk T is arithmetic";
// ... your implementation here ...
}
else
{
// throw an exception or do what ever you want,
// here a compile-time error
static_assert(!std::is_same_v<T, T>, "not implemented yet...");
}
}
main()
{
Test<int> t;
t.print();
Test<void> t2;
// t2.print(); <- will generate a compile time error
}

Cannot understand friend functions in a template class

This is code i have written to understand the concept. The code is fine and it runs.
What i dont understand is that why is the marked line needed ?
template <class T>
class D
{
public :
template <class P> //<------------------Why is this needed ? --------------
friend void print(D <P> obj);
};
template <class T>
void print(D<T> obj)
{std::cout<<sizeof(T);};
int main()
{
D <char>obj3;
print(obj3);
return 0;
}
or in other words why does the following not run ?
template <class T>
class D
{
public :
friend void print(D <T> obj);
};
As per [temp.friend], you must provide explicit template arguments to make a specialisation of a template function a friend:
template <class T>
class D
{
public :
friend void print<T>(D <T> obj);
};
Without it, the compiler will be looking for a function print(), not a function template print().

friend function of a templated class needs access to member type

I need to define a friend function for the templated class. The function has
return type that is a member type of the class. Now, I can not declare it beforehand, since the the return type is not known at the time. Something like this
template<class T> class A;
//This doesn't work: error: need ‘typename’ before...
template<class T> A<T>::member_type fcn(A<T>::member_type);
//This doesn't work: error: template declaration of ‘typename...
template<class T> typename A<T>::member_type fcn(A<T>::member_type);
template<class T>
class A{
public:
typedef int member_type;
friend member_type fcn<T>(member_type);
};
How do I do this?
I managed to compile that code on g++ using :
template<class T> typename A<T>::member_type fcn(typename A<T>::member_type);
(Thus a second 'typename' was required)
You need to say typename also in the argument:
template <class T>
typename A<T>::member_type fcn(typename A<T>::member_type);
// ^^^^^^^^
Otherwise there's no problem with your code, as long as all the template definitions appear before the function template is first instantiated.
It seems that in your particular example nothing in fcn function actually depends on class A. It doesn't even need to access any of the A's methods/fields, neither public nor protected/private. So it doesn't make sense. It would have made some sense otherwise, but at any rate it seems like it is worth re-thinking your problem and come up with a cleaner solution that does not need a hack like that. If, after a deep thought, you still believe you need it, you can do something like this:
#include <cstdio>
template<typename T> typename T::member_type fcn(const T & v) {
return v.value_;
}
template<class T>
class A {
public:
typedef T member_type;
friend member_type fcn< A<T> >(const A<T> &);
A() : value_(1986) {}
private:
T value_;
};
int main()
{
A<int> a;
printf("The value is: %d\n", fcn(a));
}
Notable thing in the above example is that you need to de-couple a cross dependency and make your free-function not depend on a declaration of class A. If you still feel like you need that coupling, the following code works, too:
#include <cstdio>
template <typename T>
class A;
template <typename T> typename A<T>::member_type fcn(const A<T> & v) {
return v.value_;
}
template <typename T>
class A {
public:
typedef int member_type;
friend member_type fcn<T>(const A<T> &);
A() : value_(1986) {}
private:
member_type value_;
};
int main()
{
A<void> a;
printf("The value is: %d\n", fcn(a));
}
Hope it helps. Good Luck!
This may by now be redundant with someone else's answer, but here's a complete, testable solution. The final function definition is a template specialization of fcn, which will produce a compiler error indicating that A<double>::x is not accessible from fcn<int>, but A<int>::x is accessible.
template<class T> class A;
template <typename U>
typename A<U>::member_type fcn(typename A<U>::member_type);
template<class T>
class A {
int x;
public:
typedef int member_type;
friend typename A<T>::member_type fcn<T>(typename A<T>::member_type);
};
template<>
int fcn<int>(int x)
{
A<int> i;
A<double> d;
i.x = 0; // permitted
d.x = 0; // forbidden
return 0;
}