is it possible to somehow make a partial template specification a friend class? I.e. consider you have the following template class
template <class T> class X{
T t;
};
Now you have partial specializations, for example, for pointers
template <class T> class X<T*>{
T* t;
};
What I want to accomplish is that every possible X<T*> is a friend class of X<S> for ANY S. I.e. X<A*> should be a friend of X<B>.
Of course, I thought about a usual template friend declaration in X:
template <class T> class X{
template <class S> friend class X<S*>;
}
However, this does not compile, g++ tells me this:
test4.cpp:34:15: error: specialization of 'template<class T> class X' must appear at namespace scope
test4.cpp:34:21: error: partial specialization 'X<S*>' declared 'friend'
Is this not possible at all or is there some workaround?
The reason why I am asking is that I need a constructor in X<T*> that creates this class from an arbitrary X<S> (S must be a subtype of T).
The code looks like this:
template <class T> class X<T*>{
T* t;
template<class S>
X(X<S> x) : t(&(x.t)) {} //Error, x.t is private
}
Now, the compiler complains, of course, that x.t is not visibile in the constructor since it is private. This is why I need a partial specialization friend class.
In C++, you can grant access beyond private on four levels.
completely public access (see pmr's answer)
access within inheritance hierarchy (protected, irrelevant here)
to a base template friend (see this answer)
to a non-template or fully specialized friend (too weak to solve your use case)
There is no middle way between the two latter kinds of friendship.
From §14.5.4 of the C++ standard:.
Friend declarations shall not declare partial specializations.
The following declaration will allow you to implement what you need. It gives you a free hand to access any specialization of your template from any other specialization, but still only within X. It is slightly more permissive than what you asked for.
template<class T> class X
{
template<class Any> friend class X;
public:
...
};
We can define a getter protected by a key defined in X.
#include <type_traits>
template <class T> class X{
T t;
public:
struct Key {
template<typename S>
Key(const X<S>&) {
static_assert(std::is_pointer<S>::value, "Not a pointer");
}
};
const T& get(Key) const { return t; }
T& get(Key) { return t; }
};
template <class T> class X<T*> {
T* t;
public:
template<class S>
X(X<S>& x) : t(&(x.get(typename X<S>::Key(*this)))) {}
};
int main()
{
X<int> x1;
X<int*> x2(x1);
return 0;
}
This still has some weakness. Everybody with an X<T*> can now use
get. But this is so obfuscated by now, that no one is goiing to
realize that. I'd choose a simple public getter.
Related
I'm trying to access a parent method from a derived template class, but despite using public access everywhere, and "this->" to be safe, I'm getting the error.
error: 'class Derived<TagTypeA, int>' has no member named 'insert'
I don't know if I'm making a stupid mistake somewhere, but I can't work out why the Derived class can't access the parent's stuff.
I have code that looks something like below, and also here: https://godbolt.org/z/nMbe4fMnM
#include <bits/stdc++.h>
struct TagTypeA;
template<typename T>
class Base {
public:
std::set<T> data;
void insert(const T& v) { data.insert(v); }
void erase(const T& v) { data.erase(v); }
};
template<typename Tag, typename T>
class Derived : public Base<T> {};
// specialization of Derived
template<typename T>
class Derived<TagTypeA, T> {
public:
void call_parent_insert(const T& v) { this->insert(v); }
};
int main()
{
Derived<TagTypeA, int> foo;
foo.call_parent_insert(1);
}
Compiler needs a suspect base class to contain method in question in order to consider the code legal.
The class described by template specialization
template<typename T>
class Derived<TagTypeA, T> {
public:
void call_parent_insert(const T& v) { this->insert(v); }
};
declares that type Derived<TagTypeA ,T> doesn't have base class. There is nowhere it can get insert method from. Declaration should be looking like this
template<typename T>
class Derived<TagTypeA, T> : public Base<T> {
It's not necessary that insert would be defined in Base<T> at moment of this declaration. It might be defined in a specialization of Base later. It matters only at point of instantiation of Derived as you cleverly used this->insert expression.
If an unspecialized Derived never will be used, it can be declared as incomplete class. Its only purpose in that case is to declare existence of template and this case reduce amount of cryptic template errors in case of misuse.
template<typename Tag, typename T> class Derived;
I am thinking of creating template class wrapper that is supposed to inherit all of template parameter functionality and add something on top of it. For structs and classes this would be pretty simple
class foo{ void bar(){} };
template<class T>
class baz : public T { void zab(){} };
int main(){
baz<foo> a;
}
Now, my question is if there is any way to be able to keep operators for built-in integral types without tons of manual specializing template for those types to be able to do it like this:
int main(){
baz<int> a;
int b = a + 2;
}
Can it be done? If so, how? (I know it will be necessary to do it with some magic specialization. I am just asking if it is possible to do it with one partial specialization)
With SFINAE friend class, you may reduce the specializations with template:
template <class T, typename Enabler = void>
class baz : public T { void zab(){} };
// specialization for integral type
template <class T>
class baz<T, std::enable_if_t<std::is_integral<T>::value>>
{
friend auto operator + (T lhs, T rhs) { /*..*/}
operator T() const { return value; }
// ...
T value;
};
Let's say I have to following hierarchy:
template<class T> class Base {
protected:
T container;
};
template<class T> class Derived1 : public Base<T> {
public:
void f1() {
/* Does stuff with Base<T>::container */
}
};
template<class T> class Derived2 : public Base<T> {
public:
void f2() {
/* Does stuff with Base<T>::container */
}
};
Now I want an independent Class (not derived from Base) that can access the Base<T>::container directly from Base or any Derived class. I read about template friend classes and it seems to be the solution to my problem but I couldn't figure out the syntax yet.
I am looking for something like:
template<class T> class Foo{
template<T> friend class Base<T>; // <-- this does not work
public:
size_t bar(const Base<T> &b) const{
return b.container.size();
}
};
Derived1<std::vector<int> > d;
d.f1();
Foo<std::vector<int> > foo;
size_t s = foo.bar()
The friend class line causes an error: specialization of ‘template<class T> class Base’ must appear at namespace scope template<T> friend class Base<T> and the member variable container is still not accessible.
A couple of issues:
Just as you don't put a <T> after the class name when defining a class template:
template <class T> class X<T> { ... }; // WRONG
template <class T> class X { ... }; // RIGHT
you shouldn't put it after the class name when declaring a class template, whether in a forward declaration or friend declaration:
template <class T> class X<T>; // WRONG
template <class T> class X; // RIGHT - declares the template exists
template <class T> friend class X<T>; // WRONG
template <class T> friend class X; // RIGHT - says all specializations of X are friends
(Unless you're creating a class template partial specialization. For example, if class template X is already declared, then template <class T> class X<T*> { ... }; defines a partial specialization that will be used instead of the primary template when the template argument is a pointer.)
And you have the friend declaration backwards: it needs to appear inside the class with the non-public member(s), and name the other class(es) which are allowed to use the members. (If it worked the other way around, then any new class could gain access to any other class's private and protected members, without the permission of the owning class!)
So you would need:
template <class T> class Foo;
template<class T> class Base {
template <class U> friend class Foo;
protected:
T container;
};
The forward declaration of Foo is sometimes not needed, but I think it makes things clearer, and it can avoid gotchas when things start getting more complicated with namespaces, nested classes, etc.
Only Base can say Foo is its friend.
template<typename T> friend class Foo; // every Foo<T> is a friend of Base
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;
}
assume that I have the following two template classes :
template <class _A>
class First
{
private:
int a;
};
template <class _B>
class Second
{
private:
int b;
};
how can I link them in many-to-many friendship. for example, adding a method in First that prints b of a parameter object of Second.
is my question clear?
template <typename T>
class First {
int a;
template<typename> friend class Second;
};
template <typename T>
class Second
{
int b;
template<typename> friend class First;
};
This will enable every First<T> to access the internals of every Second<U>. Now, while this is the technical solution, you might want to consider whether a design with cyclic dependencies and opening up the internal to any instantiation of the other class is the best solution to your particular problem.
BTW, if you only want to grant First<int> access to Second<int> (and not Second<double>) you can do that like so:
template <typename> class Second;
template <typename T>
class First {
int a;
friend class Second<T>; // only befriend the same instantiation
};
template <typename T>
class Second {
int b;
friend class First<T>;
};
In this second version you need the forward declaration of the Second template before befriending a particular instantiation, but this allows you to grant access to the internals of the class only to a particular instantiation.
Assuming you understand protection, is the issue forward declaration of templates:
#include <iostream>
template <class _B> class Second; // Forward declare
template <class _A>
class First
{
public:
template<class _B>
void print(const Second<_B>& b)
{
std::cout << b.b << std::endl;
}
int a;
};
template <class _B>
class Second
{
public:
int b;
};
void testIt()
{
Second<double> sd;
First<int >fi;
fi.print<double>(sd);
}
You could start off with a declaration of each class:
template< typename T > class First;
template< typename T > class Second;
And now both classes will know about the other one in their definitions. You can declare them as friends there if you need to.
template< typename T > class First
{
template< typename U> friend class Second;
};
and the same in reverse.
You can also implement function bodies under the class definitions if they need to see each other's details, i.e. they cannot use a "forward declaration" copy.