Interdependent class templates design? - c++

Consider the following design :
template <class SecondType>
struct First
{
SecondType* _ptr;
};
template <class FirstType>
struct Second
{
FirstType* _ptr;
};
where the First type has a pointer to a Second type and vice-versa. The problem is that I cannot declare this because they are interdependent and I should declare First<Second<First<Second...>>>.
How to solve this problem ?

Maybe a work-around with something that looks like CRTP but even crazier:
#include <iostream>
template <class SecondType>
struct FirstBase
{
SecondType* _ptr;
};
template <class FirstType>
struct SecondBase
{
FirstType* _ptr;
};
struct FirstDerived
: public FirstBase<SecondBase<FirstDerived>>
{
};
struct SecondDerived
: public SecondBase<FirstBase<SecondDerived>>
{
};
int main()
{
FirstBase<SecondDerived> x;
SecondBase<FirstDerived> y;
return 0;
}
If someone has a more elegant way to do this, I would be happy to see it.

Not sure what you are trying to achieve but the following compiles fine.
template <class T> struct First { T* _ptr; };
template <class T> struct Second { T* _ptr; };
int main(){
First<Second<First<Second<void>>>> a; // or
First<Second<First<Second<nullptr_t>>>> b;
return 0;
}
Note I replaced FirstType, SecondType altogether cos it does not matter. T would be replaced by whatever you pass and this will happen when the template is being specialized before compilation.

Here is another possibly more elegant solution which doesn't require void at all. I don't know if the inheritance is acceptable to you but I think it works well.
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
struct Base {
//make all functions virtual
};
template <class SecondType>
struct First: public Base
{
SecondType* _ptr;
First(SecondType * st) {
_ptr = st;
}
First() {
}
};
template <class FirstType>
struct Second: public Base
{
FirstType* _ptr;
Second(FirstType * ft) {
_ptr = ft;
}
Second() {
}
};
int main() {
First<Base> f;
Second<Base> s;
f._ptr = &s;
s._ptr = &f;
cout << s._ptr << endl;
}

Related

How does one specialize a template for all non-array types?

Let's say I have a template my_type. I want it to have general functionality, to have a few extra functions when T is not an array and to have others when T is an array.
Let's say I have the following template:
template <typename T>
class my_class<T> {
public:
int f1(); // This function is available for all T
int f2(); // This function is available when T is not an array
int f3(); // This function is available when T is an array
}
So if I try:
my_class<int> c1; my_class<int[3]> c2;
c1.f1(); c2.f1(); // both fine
c1.f2(); c2.f3(); // both fine
c1.f3(); c2.f2(); // both should give a compile error
I am aware std::unique_ptr does this internally. So how does it do it?
Another way, using enable_if. Note also the use of a base class to capture all common behaviour.
#include <type_traits>
template<class T>
struct my_base
{
int f1();
};
template<class T, typename Enable = void>
class my_class;
template<class T>
class my_class<T, std::enable_if_t<std::is_array<T>::value>>
: public my_base<T>
{
public:
int f3(); // This function is available when T is an array
};
template <typename T>
class my_class<T, std::enable_if_t<not std::is_array<T>::value>>
: public my_base<T>
{
public:
int f2(); // This function is available when T is not an array
};
int main()
{
auto a = my_class<int[]>();
a.f1();
// a.f2();
a.f3();
auto na = my_class<int>();
na.f1();
na.f2();
// na.f3();
}
I have figured it out myself. The following code will do the exact thing I have asked for.
template<typename T>
class my_class {
public:
int f1() { return 1; }
int f2() { return 2; }
};
template<typename T>
class my_class<T[]> {
public:
int f1() { return 1; }
int f3() { return 3; }
};
Note that the implementation of the common function (f1) had to be copied. Now is there a way to use a single implementation? (note that it is NOT as simple as a return 1; like in the example code and thus I can't separate functionality into a non-template function)

Can we add a friend class based on template parameter?

I wonder whether the below tricky situation is possible:
Suppose I have a template class template <typename DTYPE> class A{};, where DTYPE is supposed to be one of uint8_t, uint16_t, etc. I want to add a friend class to A, but this friend class differs for each DTYPE alternative. Further, suppose the friend classes for different DTYPE values are not instantiations of another template class, but independent classes.
Is there a way to do it?
You can add template "proxy" class FriendOfA and specialize it for whatever type you need:
// actual friends
class FriendUint8 {};
class FriendUint16 {};
template<typename T> struct FriendOfA;
template<>
struct FriendOfA<uint8_t> {
typedef FriendUint8 type;
};
template<>
struct FriendOfA<uint16_t> {
typedef FriendUint16 type;
};
// optional helper
template <typename T>
using FriendOfA_t = typename FriendOfA<T>::type;
template<class T>
class A {
friend typename FriendOfA<T>::type;
// or simply
friend FriendOfA_t<T>;
};
I believe you're looking for something like that:
#include <iostream>
struct BaseFriend
{
template <typename T>
void boo(const T& t) { t.foo(); }
};
struct BaseFriendProxy
{
template <typename T>
void boo(const T& t) { std::cout << "Proxy: "; t.foo(); }
};
template <typename TType>
struct Friend ;
template <>
struct Friend<int> {
using T = BaseFriend;
};
template <>
struct Friend<char> {
using T = BaseFriendProxy;
};
template <typename DTYPE>
class A
{
private:
friend typename Friend<DTYPE>::T;
void foo() const
{ std::cout << "A::foo()" << std::endl; }
};
int main()
{
A<int> a;
BaseFriend bf1;
bf1.boo(a);
A<char> b;
BaseFriendProxy bf2;
bf2.boo(b);
return 0;
}
But this will work only with C++11: you can't combine friend class ... with typename X::Y in C++03
Sure you can, specialize your template and add whatever friend class you want:
#include <iostream>
using namespace std;
class base {
public:
virtual int getValue() = 0;
};
class friend1 {
public:
base* ptr;
int getValue() {
return ptr->getValue();
}
};
class friend2 {
public:
base* ptr;
int getValue() {
return ptr->getValue();
}
};
template <typename DTYPE> class A : public base{
public:
A() { data = 42; }
// No friends
private:
int data;
int getValue() {
return data;
}
};
template <> class A<char> : public base{
public:
A() { data = 44; }
friend class friend1;
private:
int data;
int getValue() {
return data;
}
};
template <> class A<bool> : public base{
public:
A() { data = 45; }
friend class friend2;
private:
int data;
int getValue() {
return data;
}
};
int main()
{
A<char> obj1;
friend1 friend_of_obj1;
friend_of_obj1.ptr = &obj1;
cout << friend_of_obj1.getValue() << endl;
A<bool> obj2;
friend2 friend_of_obj2;
friend_of_obj2.ptr = &obj2;
cout << friend_of_obj2.getValue();
}
http://ideone.com/hM9x0y
Yes, a friend can be based on a template. Such as;
template <typename DTYPE>
struct Friend;
template <class DTYPE>
class A {
friend struct Friend<DTYPE>;
};
For each type DTYPE for the class A you wish to support (different by implementation) you can specialise Friend, such as;
template<>
struct Friend<uint8_t> {
// ...
};
A basic working sample:
#include <cstdint>
using namespace std;
template<typename T>
struct Friend;
template <class T>
class A {
friend struct Friend<T>;
int i = 0;
};
template<>
struct Friend<uint8_t> {
void method() {
A<uint8_t> a;
a.i = 8;
}
};
template<>
struct Friend<uint16_t> {
void method() {
A<uint16_t> a;
//A<uint8_t> b; // fails to compile
a.i = 16;
}
};
int main()
{
A<uint8_t> a;
Friend<uint8_t> f;
f.method();
}

Getting non-const type in template

I have a template class that can (and sometimes has to) take a const type, but there is a method that returns a new instance of the class with the same type, but should be explicitly non-const. For example, the following code fails to compile
template<class T> class SomeClass {
public:
T val;
SomeClass(T val) : val(val) {}
SomeClass<T> other() {
return SomeClass<T>(val);
}
};
int main() {
SomeClass<const int> x(5);
SomeClass<int> y = x.other();
return 0;
}
because even though there's a copy on val during the constructor, it's copying to the same type - const int. Just like you can distinguish between T and const T in a template, is there a way to distinguish between T and "nonconst T"?
SomeClass<typename std::remove_const<T>::type> other()
{
return SomeClass<typename std::remove_const<T>::type>(val);
}
std::remove_const is from <type_traits> and is C++11. There's probably a boost::remove_const in Boost.TypeTraits, or you can even roll your own. It's also possible to use std::remove_cv.
You can either use std::remove_const if you are using c++ 11. Otherwise, you can use this:
struct <typename T>
struct remove_const
{
typedef T type;
};
struct <typename T>
struct remove_const<const T>
{
typedef T type;
};
Which does the same.
The problem in essence, is that there are two distinct types which are not strictly convertible.
You can use/return std::remove_const from type_traits:
#include <type_traits>
template<class T>
class SomeClass {
public:
T val;
SomeClass(T p) : val(p) {
}
SomeClass<typename std::remove_const<T>::type> other() {
return static_cast<SomeClass<typename std::remove_const<T>::type> >(val);
}
};
int main() {
SomeClass<const int>x(5);
SomeClass<int>y = x.other();
return 0;
}

Refactoring c++ template class based on template type

Given class Foo
template <typename T>
class Foo
{
public:
...other methods..
void bar()
{
...
m_impl.doSomething();
...
}
void fun()
{
...
m_impl.doSomethingElse();
...
}
void fubar()
{
...
}
private:
T m_impl;
};
I wanted to cater for situations where T is a boost::shared_ptr.
In this case the only change to class Foo is that it should invoke
m_impl->doSomething();
instead of
m_impl.doSomething();
I ended up defining FooPtr in the same header
template <typename T>
class FooPtr
{
public:
...other methods..
void bar()
{
...
m_pImpl->doSomething();
...
}
void fun()
{
...
m_pImpl->doSomethingElse();
...
}
void fubar()
{
...
}
private:
boost::shared_ptr<T> m_pImpl;
};
Now while the approach works for all classes that I want to use with Foo,
the problem is that I have a lot of duplicate code lying around and any changes
I make to Foo, I also have to make to FooPtr.
How can I refactor the code? E.g. Is there any way that I can determine at compile time if T is of type boost::shared_ptr, and then specialise just the bar and fun methods to invoke the -> operator?
Edit:
Thanks for all the answers so far! I just need some time to work through them all and see which solution is the best fit for our software.
Edit 2:
#Matthieu: This is the test code I was using
class FooImpl
{
public:
void doIt()
{
cout << "A" << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Foo<FooImpl> foo;
foo.doSomething();
return 0;
}
Sylvain wrote a DRY solution, but I don't like abusing inheritance.
Using a wrapper class to uniformize the interface is easy, especially since pointer semantics work so well!
namespace details {
template <typename T>
struct FooDeducer {
typedef boost::optional<T> type;
};
template <typename T>
struct FooDeducer< T* > {
typedef T* type;
};
template <typename T>
struct FooDeducer< boost::shared_ptr<T> > {
typedef boost::shared_ptr<T> type;
};
} // namespace details
template <typename T>
class Foo {
public:
// methods
void doSomething() { impl->doIt(); }
private:
typedef typename details::FooDeducer<T>::type Type;
Type impl;
};
Here, relying on boost::optional which provides the OptionalPointee semantics, we nearly get the same behavior than pointers.
One point I'd like to emphasize though, is the difference in the copying behavior. boost::optional provides deep copy.
class A
{
public:
void doSomething() {}
};
template <typename T>
class Foo
{
public:
void bar()
{
Impl(m_impl).doSomething();
}
private:
template<typename P>
P& Impl(P* e)
{
return *e;
}
template<typename P>
P& Impl(std::shared_ptr<P> e)
{
return *e;
}
template<typename P>
P& Impl(P& e)
{
return e;
}
T m_impl;
};
You can write a caller class template, whose job is to call the function, either using syntax obj.f() or obj->f(), based on the type of obj.
Here is a small example that demonstrates this approach:
template<typename T>
struct caller
{
static void call(T &obj) { obj.f(); } //uses obj.f() syntax
};
template<typename T>
struct caller<T*>
{
static void call(T* obj) { obj->f(); } //uses obj->f() syntax
};
And this caller class template is used by this sample class:
template<typename T>
struct X
{
T obj;
X(T o) : obj(o) {}
void h()
{
caller<T>::call(obj); //this selects the appropriate syntax!
}
};
See this online running demo at ideone : http://www.ideone.com/H18n7
--
EDIT:
This is even more generic. Here you can even pass the function which you want to call in caller. Now caller is not hard-coded with the function to be called!
http://www.ideone.com/83H52
I really question whether you should be using a template here at all. Your template parameter has a very clear interface and therefore looks like you should just use an abstract base class.
Do you really need to have an instance? If you do need to change the way the object is represented, this should be done as a separate exercise and not part of the template that uses it.
You can introduce another intermediate template class, something like that:
template < typename T >
class FooBase
{
private:
T m_impl;
protected:
T& impl() { return m_impl; }
};
template < typename T >
class FooBase< boost::shared_ptr< T > >
{
private:
boost::shared_ptr< T > m_impl;
protected:
T& impl() { return *(m_impl.operator ->()); }
};
template < typename T >
class Foo : protected FooBase< T >
{
public:
void bar()
{
impl().DoSomething();
}
};
Now, you only have to code the Foo class only once. And you can specialize it for other smart pointers type by doing partial specialization on FooBase.
Edit: You can also use composition instead of having an inheritance relationship between Foo and FooBase (in which case, I'd probably rename it to FooHelper or something like that).
template < typename T >
class FooHelper
{
private:
T m_impl;
public:
T& impl() { return m_impl; }
};
template < typename T >
class FooHelper< boost::shared_ptr< T > >
{
private:
boost::shared_ptr< T > m_impl;
public:
T& impl() { return *(m_impl.operator ->()); }
};
template < typename T >
class Foo
{
private:
FooHelper< T > m_helper;
public:
void bar()
{
m_helper.impl().DoSomething();
}
};
You can use partial specialization.
template <typename T>
class Foo
{
public:
//...
};
template<typename T> class Foo<boost::shared_ptr<T>> {
//... implement specialization here
};

Check if template argument is inherited from class

I want to check if the type given to a template is inherited from a base class in my project.
It should work like one would expect it from the following example:
template< class T : public CBaseClass >
Is it possible to do this with templates, if not, how else can I do it?
Following an example from Stroustrup:
template<class Test, class Base>
struct AssertSameOrDerivedFrom {
AssertSameOrDerivedFrom() { &constraints; }
public:
static void constraints() {
Test *pd = 0;
Base *pb = pd;
}
};
template<class T>
struct YourClass {
YourClass() {
AssertSameOrDerivedFrom<T, CBaseClass>();
}
};
In C++0x, this becomes:
template<class T>
struct YourClass {
static_assert(std::is_base_of<CBaseClass, T>::value);
};
You can use boost::is_base_and_derived from Boost, combined with BOOST_STATIC_ASSERT. If you are using a compiler with TR1 or C++0x support, there are equivalents of those constructs in the standard library (std::is_base_of, and the static_assert statement in C++0x).
If you want to assert, do it Nurk's way. If you want to check, use is_base_of from boost or C++0x. If you can't use either of those, use SFINAE:
template < typename Base, typename PotentialDerived >
struct is_base
{
typedef char (&no) [1];
typedef char (&yes) [2];
static yes check(Base*);
static no check(...);
enum { value = sizeof(check(static_cast<PotentialDerived*>(0))) == sizeof(yes) };
};
The simplest solution seems to be std::is_base_of:
static_assert(std::is_base_of_v<CBaseClass, T>);
You can of course also use it in combination with if constexpr:
if constexpr (std::is_base_of_v<CBaseClass, T>) {
//
} else {
//
}
See cppreference for more details:
https://en.cppreference.com/w/cpp/types/is_base_of
Shorter is better:
template <typename Base, typename Derived>
struct is_base {
constexpr static bool check(Base*) { return true; }
constexpr static bool check(...) { return false; }
enum { value = check(static_cast<Derived*>(0)) };
};
Example 1:
struct A {};
struct B : A { };
int main(void) {
static_assert(is_base<A,B>::value, "If Error: A is not base of B");
}
Example 2:
template <bool, typename T=void>
struct Use {
static std::string info() { return "Implementation that consider that A is not base of B"; }
};
template <typename T>
struct Use<true,T> {
static std::string info() { return "Implementation that consider that A is the base of B"; }
};
int main(void) {
std::cout << Use<is_base<A,B>::value>::info(); //Implementation that consider that A is the base of B
}