Some background: I'm writing a policy-based smart pointer (like SmartPtr in the Loki library), which can have destructive copy semantics like auto_ptr. Therefore, it needs to have a template copy constructor taking non-const reference to modify the object being copied.
What I'm trying to do is to parametrize the constness of the argument taken by copy constructor by some variable in the policy to make it const when destructive copy semantics is not desired. Here is the simplified code of the idea I've came up to, but, unfortunately, it doesn't work, because the compiler can't deduce template arguments. I there any other technique that can be used to achieve the desired behaviour?
template <typename T, bool isEnabled> struct AddConst {
typedef T Type;
};
template <typename T> struct AddConst<T, true> {
typedef const T Type;
};
struct MyCopyPolicy {
static const bool kIsCopyArgConst = true;
};
template <typename T, class CopyPolicy> struct Foo {
// A helper struct to achieve "template typedef".
template <typename T2> struct CopyArg {
typedef typename AddConst<Foo<T2, CopyPolicy>,
CopyPolicy::kIsCopyArgConst>::Type Type;
};
Foo() {}
// Template copy constructor. Doesn't work.
template <typename T2> Foo(typename Co开发者_如何学运维pyArg<T2>::Type& rhs) {}
};
int main() {
Foo<int, MyCopyPolicy> foo1;
Foo<double, MyCopyPolicy> foo2 = foo1; // error!
}
Perhaps something like this might work for you. I've used std::enable_if from C++0x. You could just as easily use boost's, or roll your own (it's only a couple lines of code).
#include <type_traits>
struct MyCopyPolicy {
static const bool kIsCopyArgConst = true;
};
template <typename T, class CopyPolicy> struct Foo {
// A helper struct to achieve "template typedef".
template <typename T2> struct CopyArg {
typedef CopyPolicy Type;
};
Foo() {}
template <typename T2>
Foo(const T2& rhs,
typename std::enable_if<CopyArg<T2>::Type::kIsCopyArgConst>::type* = 0)
{}
template <typename T2>
Foo(T2& rhs,
typename std::enable_if<!CopyArg<T2>::Type::kIsCopyArgConst>::type* = 0)
{}
};
int main() {
Foo<int, MyCopyPolicy> foo1;
Foo<double, MyCopyPolicy> foo2 = foo1; // ok!
}
I'm not positive this is optimal. This was just shoot-from-the-hip with one of the goals being a minimum distance from where you were heading. Perhaps this is where you want to go, or perhaps this will just get you started in the right direction.
精彩评论