-
October 27th, 2009, 04:22 AM
#1
[RESOLVED] Template const & non-const versions
I'm pretty sure this can't be done the way I'd like, but I thought I'd put it past you lot first.
I have two classes.
Code:
class Test
{
public:
void Set(int &i)
{
p_i = &i;
}
int *Get()
{
return p_i;
}
private:
int *p_i;
};
class Const_Test
{
public:
void Set(const int &i)
{
p_i = &i;
}
const int *Get()
{
return p_i;
}
private:
const int *p_i;
};
What I would like to do is have one templated class where I can specify whether to use 'const' or not.
The only solution I have come up with so far is to specify the whole type i.e. 'int' or 'const int'
Code:
template <typename T>
class Test
{
public:
void Set(T &i)
{
p_i = &i;
}
T *Get()
{
return p_i;
}
private:
T *p_i;
};
Test<int> test;
Test<const int> const_test;
Any alternative ideas?
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
October 27th, 2009, 04:40 AM
#2
Re: Template const & non-const versions
maybe something like
Code:
#include <boost/type_traits.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/apply.hpp>
namespace mpl = boost::mpl;
template <typename ArgPolicy = mpl::identity<mpl::_1> >
class Test
{
public:
typedef int BaseType;
typedef typename mpl::apply<ArgPolicy, BaseType>::type ArgType;
void Set(ArgType &i)
{
p_i = &i;
}
ArgType *Get()
{
return p_i;
}
private:
ArgType *p_i;
};
Test<> a;
Test< boost::add_const<mpl::_1> > const_a;
-
October 27th, 2009, 09:14 AM
#3
Re: Template const & non-const versions
It's not clear to me what your are trying to do, but maybe you should consider overloading functions with const versions:
Code:
int *Get()
{
return p_i;
}
const int *Get() const
{
return p_i;
}
If that's not what you need, try should how you would like to use the Test class even if it won't compile.
-
October 27th, 2009, 09:53 AM
#4
Re: Template const & non-const versions
The class is used as a functor for std::for_each in const & non-const variations of another class' function.
The const function requires that the functor be defined with const members.
What I want is not to have to write the functor twice, as shown below.
Code:
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
// Non-const functor
class Functor
{
public:
Functor()
: p_i(0)
{
}
void operator()(int &i)
{
if (i == 10)
{
p_i = &i;
}
}
int *Result()
{
return p_i;
}
int *p_i;
};
// Const functor
class Const_Functor
{
public:
Const_Functor()
: p_i(0)
{
}
void operator()(const int &i)
{
if (i == 10)
{
p_i = &i;
}
}
const int *Result()
{
return p_i;
}
const int *p_i;
};
//**************************************
struct Test
{
Test()
: data(10, 0)
{
data[3] = 10;
}
// Non-const Find
int *Find()
{
Functor f = for_each(data.begin(), data.end(), Functor());
return f.Result();
}
// Const Find
const int *Find() const
{
Const_Functor f = for_each(data.begin(), data.end(), Const_Functor());
return f.Result();
}
// Const print
void Print() const
{
// Look for 10.
const int *p_i = Find();
if (p_i != 0)
{
cout << *p_i;
}
else
{
cout << "Not found";
}
}
vector<int> data;
};
//**************************************
int main()
{
Test t;
t.Print();
}
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
October 27th, 2009, 10:21 AM
#5
Re: Template const & non-const versions
if you don't want to use boost, then you could write something like
Code:
template <typename T>
struct DefaultTest { typedef T type; };
template <typename T>
struct ConstTest { typedef const T type; };
template < template <typename T> class TestType = DefaultTest >
class Test
{
public:
typedef typename TestType<int>::type ArgType;
void Set(ArgType &i)
{
p_i = &i;
}
ArgType *Get()
{
return p_i;
}
private:
ArgType *p_i;
};
Test<> test;
Test<ConstTest> const_test;
-
October 27th, 2009, 11:27 AM
#6
Re: Template const & non-const versions
Originally Posted by JohnW@Wessex
The class is used as a functor for std::for_each in const & non-const variations of another class' function.
I once had a similar problem to implement two versions of iterators: a const and a non-const one. If I remember correctly, I saw this idea at SGI's STL.
Create a const traits and then model your class based on that level of indirection.
Code:
template <class value_t>
struct const_traits
{
typedef value_t value_type;
typedef const value_t* pointer;
typedef const value_t& reference;
};
template <class value_t>
struct non_const_traits
{
typedef value_t value_type;
typedef value_t* pointer;
typedef value_t& reference;
};
template <class constness_traits_t>
class functor
{
typedef typename constness_traits_t::value_type value_type;
typedef typename constness_traits_t::pointer pointer;
typedef typename constness_traits_t::reference reference;
void operator()(reference i);
/*... */
};
Last edited by ltcmelo; October 27th, 2009 at 12:00 PM.
-
October 27th, 2009, 11:32 AM
#7
Re: Template const & non-const versions
Some interesting ideas
I'll have to give them some thought.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
October 27th, 2009, 11:46 AM
#8
Re: Template const & non-const versions
It looks like your initial solution with two typedefs is the best one. If something can be solved by simple way, there is not need for complicated version.
Code:
template<class T>
class Functor
{
public:
Functor()
: p_i(0)
{
}
void operator()(T &i)
{
if (i == 10)
{
p_i = &i;
}
}
T *Result()
{
return p_i;
}
T *p_i;
};
typedef Functor<int> NormalFunctor;
typedef Functor<const int> ConstFunctor;
int _tmain(int argc, _TCHAR* argv[])
{
int n = 0;
NormalFunctor n1;
ConstFunctor n2;
n1(n);
n2(n);
return 0;
}
Notice that NormalFunctor and ConstFunctor look like STL iterator and const_iterator, pretty standard for a user.
But if we want to make NormalFunctor and ConstFunctor typedefs not only for int type? Typedef cannot be templated, but there is solution with helper template:
Code:
template<class T>
class Functor
{
public:
Functor()
: p_i(0)
{
}
void operator()(T &i)
{
if (i == 10)
{
p_i = &i;
}
}
T *Result()
{
return p_i;
}
T *p_i;
};
template<class T>
struct FunctorType
{
typedef Functor<T> NormalFunctor;
typedef Functor<const T> ConstFunctor;
};
int _tmain(int argc, _TCHAR* argv[])
{
int n = 0;
FunctorType<int>::NormalFunctor n1;
FunctorType<int>::ConstFunctor n2;
n1(n);
n2(n);
short k = 0;
FunctorType<short>::NormalFunctor k1;
FunctorType<short>::ConstFunctor k2;
k1(k);
k2(k);
return 0;
}
-
October 28th, 2009, 04:48 AM
#9
Re: Template const & non-const versions
Thanks for all the ideas guys.
What I used in the end was like superbonzo's idea but makes use of the TR1 type traits classes.
Code:
#include <algorithm>
#include <vector>
#include <iostream>
#include <type_traits>
using namespace std;
using namespace std::tr1;
// Functor
template<template<typename> class Traits>
class Functor
{
public:
typedef typename Traits<int>::type Type;
Functor()
: p_i(0)
{
}
void operator()(Type &i)
{
if (i == 10)
{
p_i = &i;
}
}
Type *Result() const
{
return p_i;
}
Type *p_i;
};
//**************************************
struct Test
{
Test()
: data(10, 0)
{
data[3] = 10;
}
// Non-const Find
int *Find()
{
Functor<remove_const> f = for_each(data.begin(), data.end(), Functor<remove_const>());
return f.Result();
}
// Const Find
const int *Find() const
{
Functor<add_const> f = for_each(data.begin(), data.end(), Functor<add_const>());
return f.Result();
}
// Const Print.
void Print() const
{
// Look for 10.
const int *p_i = Find();
if (p_i != 0)
{
cout << *p_i << "\n";
}
else
{
cout << "Not found\n";
}
}
// Non-const Change.
void Change()
{
// Look for 10.
int *p_i = Find();
if (p_i != 0)
{
*p_i = 20;
cout << "Changed to 20\n";
}
else
{
cout << "Not found\n";
}
}
vector<int> data;
};
//**************************************
int main()
{
Test t;
t.Print();
t.Change();
t.Print();
}
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|