template class specialization

I would like to have a template class that can automatically detect whether its template is of the form std::shared_ptr<T>. In particular, I would like to implement the class as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template <typename T>
class MyTemplateClass {
public:
  MyTemplateClass(const T& t) { obj = t; }
  void doWork() { obj.doSomething(); }
private:
  T obj;
}

template <typename T>
class MyTemplateClass<std::shared_ptr<T> > {
public:
  MyTemplateClass(const std::shared_ptr<T>& t) { obj_ptr = t; }
  void doWork() { obj->doSomething(); }
private:
  std::shared_ptr<T> obj_ptr;
}

int main() {
  TestObj obj1;
  std::shared_ptr<TestObj> obj2;

  MyTemplateClass<TetsObj> t1(obj1);
  MyTemplateClass<TetsObj> t2(obj2);
}


The second line fail as the template argument is not of the form "std::shared_ptr<TestObj>". However this is exactly the form I am looking for. How would I get around this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <memory>

template< typename T > struct my_class {

  explicit my_class( const T& t ) : obj(t) {}
  void doWork() { obj.doSomething(); }

  private: T obj;
};

template< typename T > struct my_class< std::shared_ptr<T> > {

  explicit my_class( const std::shared_ptr<T>& t ) : obj_ptr(t) {}
  void doWork() { if(obj_ptr) obj_ptr->doSomething(); }

  private: std::shared_ptr<T> obj_ptr;
};

template < typename T > // syntactic sugar
my_class<T> make_my_class( const T& v ) { return my_class<T>(v) ; }

int main() {

  struct test
  {
      void doSomething() const { std::cout << "TestObj::doSomething()\n" ; }
  } test_obj ;

  auto sptr = std::make_shared<test>() ;

  //////////// specify the correct type ///////////////////
  my_class<test> t1(test_obj);
  t1.doWork() ;

  my_class< decltype(sptr) > t2(sptr);
  t2.doWork() ;
  //////////////////////////////////////////////////////////

  ///////////////// use syntactic sugar to deduce the correct type //////////
  auto t3 = make_my_class(test_obj) ;
  t3.doWork() ;

  auto t4 = make_my_class(sptr) ;
  t4.doWork() ;
  //////////////////////////////////////////////////////////

  ////////// let the compiler deduce the type (only in C++17) //////////////

  my_class t5(test_obj) ;
  t5.doWork() ;

  my_class t6(sptr) ;
  t6.doWork() ;

  //////////// C++17 /////////////////
}

http://coliru.stacked-crooked.com/a/75ac34486efa1a7b
my 2c using type_traits:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <memory>
#include <type_traits>

template<typename T> struct is_shared_ptr : std::false_type {}; 
template<typename T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {}; //to detect std::share_ptr types

template<typename T, typename Enable = void> // primary template
struct my_class
{
    explicit my_class( const T& t ) : obj(t) {}
    void doWork() const { obj.doSomething(); }

    private: T obj;
};

template<typename T> // specialization for is_shared_ptr  types
struct my_class <T, typename std::enable_if<is_shared_ptr<T>::value>::type>
{
    explicit my_class( const T& t ) : obj_ptr(t) {}
    void doWork() const { if(obj_ptr) obj_ptr->doSomething(); std::cout << "shared_ptr version \n";}

    private: T obj_ptr;
};

template < typename T > // syntactic sugar
my_class<T> make_my_class( const T& v ) { return my_class<T>(v) ; }

int main()
{
  struct test
  {
      void doSomething() const { std::cout << "TestObj::doSomething()\n" ; }
  } test_obj ;

    auto sptr = std::make_shared<test>() ;

    my_class<test> t1(test_obj);
    t1.doWork() ;

    my_class< std::shared_ptr<test> > t2(sptr);
    t2.doWork() ;

    auto t3 = make_my_class(test_obj) ;
  t3.doWork() ;

  auto t4 = make_my_class(sptr) ;
  t4.doWork() ;
}

the difference b/w this and above proposal is that the body of my_class implementations are similar in either case with the second template parameter distinguishing whether or not a type is std::shared_ptr <>
Topic archived. No new replies allowed.