Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License or as specified alternatively below. You may obtain a copy of
8 : * the License at http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * Major Contributor(s):
16 : * Copyright (C) 2010 Red Hat, Inc., David Tardon <dtardon@redhat.com>
17 : * (initial developer)
18 : *
19 : * All Rights Reserved.
20 : *
21 : * For minor contributions see the git repository.
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
25 : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
26 : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
27 : * instead of those above.
28 : */
29 :
30 : namespace detail
31 : {
32 :
33 : template<typename T>
34 : struct has_clone
35 : {
36 : template<typename U, U x>
37 : struct test;
38 :
39 : typedef char yes;
40 : typedef struct { char a[2]; } no;
41 :
42 : template<typename U>
43 : static yes& check_sig(U*, test<U* (U::*)() const, &U::clone>* = 0);
44 : template<typename U>
45 : static no& check_sig(...);
46 :
47 : enum
48 : {
49 : value = sizeof(check_sig<T>(0)) == sizeof(yes)
50 : };
51 : };
52 :
53 : template<typename T, bool HasClone>
54 : struct cloner
55 : {
56 270 : static T* clone(T* const other)
57 : {
58 270 : return new T(*other);
59 : }
60 : };
61 :
62 : template<typename T>
63 : struct cloner<T, true>
64 : {
65 448 : static T* clone(T* const other)
66 : {
67 448 : return other->clone();
68 : }
69 : };
70 :
71 : }
72 :
73 : /** Creates a new copy of the passed object.
74 : If other is 0, just returns 0. Otherwise, if other has function
75 : named clone with signature T* (T::*)() const, the function is called.
76 : Otherwise, copy constructor is used.
77 :
78 : @returns 0 or newly allocated object
79 : */
80 : template<typename T>
81 718 : T* clone(T* const other)
82 : {
83 718 : return other ? ::detail::cloner<T, ::detail::has_clone<T>::value>::clone(other) : 0;
84 : }
85 :
86 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|