F
Ferdi Smit
I wanted to provide a template class with an optional data member. The
most natural way to do this was to implement a member for a given
template parameter, and in the case of 'void', then not.
I came up with the following, and I'm wondering if the design is any
good. Perhaps I'm overcomplicating things? Or is it ok?
// First we use a helper class that we can specialize on 'void'
template <typename T>
struct DataContainer {
// I'm aware of the problems when T is a reference, but this can
// be easily solved, either with traits, or another
// specialization
typedef T& reference_type;
T contained_;
};
// The empty class for void
template <>
struct DataContainer<void> {
typedef void reference_type;
};
// Make use of empty base class optimization to save space in
// the case of 'void'
template <typename vertex_value_type>
class Vertex : private DataContainer<vertex_value_type> {
public:
// A 'void' argument ctor
Vertex() {}
// a templated ctor taking a data argument
// SFINAE+the other overload make this work for T=void
template <typename T>
Vertex(const T& d) {
// we can't use the initializer list here, since
// the base class is dependent, and so contained_
// is not looked up, unless we qualify it. (?)
this->contained_ = d;
}
// when called in the case of 'void' this will error, which
// is good. Otherwise it works fine as the function definition
// will not be checked before use (because template class)
// and the declaration is syntactically fine.
typename DataContainer<vertex_value_type>::reference_type
data() {
return this->contained_;
}
~Vertex() {}
};
--
Regards,
Ferdi Smit (M.Sc.)
Email: (e-mail address removed)
Room: C0.07 Phone: 4229
INS3 Visualization and 3D Interfaces
CWI Amsterdam, The Netherlands
most natural way to do this was to implement a member for a given
template parameter, and in the case of 'void', then not.
I came up with the following, and I'm wondering if the design is any
good. Perhaps I'm overcomplicating things? Or is it ok?
// First we use a helper class that we can specialize on 'void'
template <typename T>
struct DataContainer {
// I'm aware of the problems when T is a reference, but this can
// be easily solved, either with traits, or another
// specialization
typedef T& reference_type;
T contained_;
};
// The empty class for void
template <>
struct DataContainer<void> {
typedef void reference_type;
};
// Make use of empty base class optimization to save space in
// the case of 'void'
template <typename vertex_value_type>
class Vertex : private DataContainer<vertex_value_type> {
public:
// A 'void' argument ctor
Vertex() {}
// a templated ctor taking a data argument
// SFINAE+the other overload make this work for T=void
template <typename T>
Vertex(const T& d) {
// we can't use the initializer list here, since
// the base class is dependent, and so contained_
// is not looked up, unless we qualify it. (?)
this->contained_ = d;
}
// when called in the case of 'void' this will error, which
// is good. Otherwise it works fine as the function definition
// will not be checked before use (because template class)
// and the declaration is syntactically fine.
typename DataContainer<vertex_value_type>::reference_type
data() {
return this->contained_;
}
~Vertex() {}
};
--
Regards,
Ferdi Smit (M.Sc.)
Email: (e-mail address removed)
Room: C0.07 Phone: 4229
INS3 Visualization and 3D Interfaces
CWI Amsterdam, The Netherlands