partial specialized templated classes

O

Olaf

Hi,

I'm working on a thin libcurl layer. Therefore I have the following classes:

template<typename T, long CURLOPT_ID>
class CurlOption: boost::noncopyable {
public:
typedef typename boost::call_traits<T>::param_type param_type;
....
public:
// constructors:
CurlOption() {}
CurlOption(param_type v) : m_value(v) {}

public:
long option() const { return CURLOPT_ID; }
result_type parameter() { return m_value; }
void setopt(CURL* handle);

private:
value_type m_value;
};

and the specialized for the templated arguments T (ether bool, long,
std::string etc.):

template<long CURLOPT_ID>
class CurlOption<bool, CURLOPT_ID> {
public:
void setopt(CURL* handle) {
curl_easy_setopt(handle,
this->option(), this->value() ? 1 : 0);
}
};

e.g. used like

struct CurlOpt {
typedef CurlOption<bool, CURLOPT_VERBOSE> Verbose;

};

and than the cURL handle class self using a double dispatch approach:

class EasyCurl : boost::noncopyable
{
public:
...
template<typename T, long ID>
void setopt(const CurlOption<T, ID>& opt) {
opt.setopt(m_curl);
}

private:
CURL* m_curl;
};


By use of this, e.g.

CurlOpt::Verbose v(on);

I get a compiler error:

EasyCurl.cpp: In member function »void EasyCurl::setVerbose(bool)«:
EasyCurl.cpp:124: Fehler: keine passende Funktion für Aufruf von
CurlOption<bool, 41l>::CurlOption(bool&)«
EasyCurl.hpp:19: Anmerkung: Kandidaten sind: CurlOption<bool,
41l>::CurlOption()
EasyCurl.hpp:19: Anmerkung: CurlOption<bool, 41l>::CurlOption(const
CurlOption<bool, 41l>&)

Obviously the right ctor is missing. Anyway, do I have all the stuff
from the Template (typedefs including) to rewrite for the specialized
template class? Or is there another way? I thought I need only to
overwrite the specialized members - where is my mistake? Is there a
better and correct way?

Thanks
Olaf
 
V

Victor Bazarov

Olaf said:
[..] I have the following
classes:

template<typename T, long CURLOPT_ID>
class CurlOption: boost::noncopyable {
public:
typedef typename boost::call_traits<T>::param_type param_type;
....
public:
// constructors:
CurlOption() {}
CurlOption(param_type v) : m_value(v) {}

public:
long option() const { return CURLOPT_ID; }
result_type parameter() { return m_value; }
void setopt(CURL* handle);

private:
value_type m_value;
};

and the specialized for the templated arguments T (ether bool, long,
std::string etc.):

template<long CURLOPT_ID>
class CurlOption<bool, CURLOPT_ID> {
public:
void setopt(CURL* handle) {
curl_easy_setopt(handle,
this->option(), this->value() ? 1 : 0);
}
};

e.g. used like

[.. some errors, with the message in German, I can't read German ..]

Obviously the right ctor is missing. Anyway, do I have all the stuff
from the Template (typedefs including) to rewrite for the specialized
template class?

Of course.
Or is there another way?

Not really.
I thought I need only to
overwrite the specialized members - where is my mistake?

Your mistake in thinking that a template specialisation contains all
stuff from the unspecialised one except the stuff you [re]define. It
does not.
Is there a
better and correct way?

Inheritance, maybe? You still can't inherit constructors, though.

V
 
O

Olaf

I thought I need only to
overwrite the specialized members - where is my mistake?

Your mistake in thinking that a template specialisation contains all
stuff from the unspecialised one except the stuff you [re]define. It
does not.
Is there a
better and correct way?

Inheritance, maybe? You still can't inherit constructors, though.

Well, I solved the problem using traits (finally I have to write about 5
specialized templates). Attached the result. Maybe there are better
ways? Class Option must be copyable by use of a temporary for Verbose
(in main). Why? Maybe better solutions here?

Thanks
Olaf



#include <iostream>
#include <string>
#include <boost/utility.hpp>
#include <boost/call_traits.hpp>


using namespace std;

enum {
VERBOSE_ID,
FILE_ID
};

template<typename T> struct OptionTraits : public boost::noncopyable { };

template<>
struct OptionTraits<bool> : public boost::noncopyable
{
static long get(bool value) { return value; }
static std::string type() { return "bool"; }
};

template<>
struct OptionTraits<std::string> : public boost::noncopyable
{
static const char* get(const std::string& value) {
return value.c_str();
}
static std::string type() { return "string"; }
};

template<typename T, long ID>
class Option // : public boost::noncopyable
{
public:
typedef typename boost::call_traits<T>::param_type param_type;
typedef T value_type;
typedef typename boost::call_traits<T>::value_type result_type;

public:
Option(param_type v) : m_value(v) {}

public:
long option() const { return ID; }
result_type parameter() { return m_value; }

public:
void setopt(int /*handle*/) const {
// work with handle; not relevant for problem here
// required is ID + value (and T bool,string etc. of course)
// for legacy API
cout << "option<"
<< OptionTraits<T>::type() << ", " << ID << ">: "
<< OptionTraits<T>::get(m_value) << "\n";
}
private:
value_type m_value;
};


typedef Option<bool, VERBOSE_ID> Verbose;
typedef Option<std::string, FILE_ID> File;


class Foo : boost::noncopyable
{
public:
Foo() : m_handle(0) {}

public:
void perform();

template<typename T, long ID>
void setopt(const Option<T, ID>& opt) {
opt.setopt(m_handle);
}
private:
int m_handle;
};

int main()
{
//Verbose v(true);
File f("bar.txt");

Foo foo;
foo.setopt(Verbose(true));
foo.setopt(f);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top