设计有一个可选的数据成员;这有什么好处吗? [英] Design to have an optional data member; is it any good?

查看:51
本文介绍了设计有一个可选的数据成员;这有什么好处吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想提供一个带有可选数据成员的模板类。

最自然的方法是为给定的

模板参数实现一个成员,如果是'void',则不是。


我想出了以下内容,我想知道这个设计是否有任何好处。也许我过度复杂了?或者可以吗?


//首先我们使用一个帮助类,我们可以专注于''无效''

模板< typename T>

struct DataContainer {

//我知道T是参考时的问题,但这可以

//轻松解决,或者具有特征,或者是其他的

//专业化

typedef T& reference_type;

T contained_;

};


//空的空类

template<>

struct DataContainer< void> {

typedef void reference_type;

};

//利用空基类优化来节省空间

//''void'的情况'

模板< typename vertex_value_type>

class Vertex:private DataContainer< vertex_value_type> {

public:

//''void''参数ctor

Vertex(){}


//一个模板化的ctor采用数据参数

// SFINAE +另一个重载使这个工作为T = void

模板< typename T>

顶点(const T& d){

//我们不能在这里使用初始化列表,因为

//基类是依赖的,所以包含_

//没有查找,除非我们符合条件。 (?)

this-> contained_ = d;

}


//在''的情况下调用void''这会出错,

//很好。否则它工作正常,因为函数定义

//在使用前不会被检查(因为模板类)

//并且声明在语法上很好。

typename DataContainer< vertex_value_type> :: reference_type

data(){

return this-> contained_;

}


~Vertex(){}

};

-

问候,


Ferdi Smit(理学硕士)

电子邮件: Fe * *******@cwi.nl

房间:C0.07电话:4229

INS3可视化和3D界面

CWI荷兰阿姆斯特丹

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: Fe********@cwi.nl
Room: C0.07 Phone: 4229
INS3 Visualization and 3D Interfaces
CWI Amsterdam, The Netherlands

推荐答案

Ferdi Smit写道:
Ferdi Smit wrote:
我想提供一个可选的模板类数据成员。最自然的方法是为给定的
模板参数实现一个成员,如果是'void',则不是。

我来了以下内容,我想知道这个设计是否合适。也许我过度复杂了?还是可以吗?


我想知道它的应用是什么?你会如何使用它?

我理解存储东西并将其取回的必要性,并且具有

typedef等等,但是这意味着什么'' 顶点<无效> ''?什么

使用你从中得到什么?


我意识到基于模板具有不同的数据内容

参数是一个有效的方法(我已经看过,如果没有写一些),

但是*有*数据的重点是什么?你不宁愿

只是未定义''DataContainer< void>''?我的意思是,声明它但不要
提供定义...

//首先我们使用一个我们可以专注于''void'的辅助类
模板< typename T>
struct DataContainer {
//我知道T是参考时的问题,但这可以很容易地解决,具有特征,或其他
//专业化
typedef T& reference_type;
T contains_;
};

// void
模板的空类<>
struct DataContainer< void> {
typedef void reference_type;
};

//利用空基类优化来节省空间
//'void'的情况
模板< typename vertex_value_type>
类顶点:私有DataContainer< vertex_value_type> {
公开:
//一个''无效''论证ctor
顶点(){}
//一个模板化的ctor采用数据参数
// SFINAE +另一个重载使得这个工作适用于T = void
模板< typename T>
Vertex(const T& d){
//我们不能使用初始化列表在这里,因为
//基类是依赖的,所以contains_
//没有查找,除非我们符合条件。 (?)
this-> contained_ = d;
}
//在''void''的情况下调用时这会出错,这个
// 很好。否则它工作正常,因为函数定义
//在使用前不会被检查(因为模板类)
//并且声明在语法上很好。
typename DataContainer< vertex_value_type> :: reference_type
数据(){
返回此 - >含有;;
}
~Vertex(){}
};
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?
I am wondering what would be the application of it? How would you use it?
I understand the need to store something and get it back, and have the
typedef, and so on, but what would be the meaning of ''Vertex<void>''? What
use do you derive from it?

I realise that having different data contents based on the template
argument is a valid approach (and I''ve seen if not written some of that),
but what would be the point of *not* having data? Wouldn''t you rather
simply undefined ''DataContainer<void>''? I mean, declare it but don''t
provide the definition...
// 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() {}
};




V



V


Victor Bazarov写道:
Victor Bazarov wrote:
Ferdi Smit写道:
Ferdi Smit wrote:
我想提供一个带有可选数据成员的模板类。最自然的方法是为给定的
模板参数实现一个成员,如果是'void',则不是。

我来了以下内容,我想知道这个设计是否合适。也许我过度复杂了?或者可以吗?
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?



我想知道它的应用是什么?你会如何使用它?
我理解需要存储并获取它,并且具有
typedef等等,但是''Vertex< void>''的含义是什么? ?你从中得到了什么?

我意识到根据模板
参数获得不同的数据内容是一种有效的方法(如果没有写的话我会看到其中一些),但是*有*数据的重点是什么?你不宁愿
只是未定义''DataContainer< void>''?我的意思是,宣布它但不提供定义...



I am wondering what would be the application of it? How would you use it?
I understand the need to store something and get it back, and have the
typedef, and so on, but what would be the meaning of ''Vertex<void>''? What
use do you derive from it?

I realise that having different data contents based on the template
argument is a valid approach (and I''ve seen if not written some of that),
but what would be the point of *not* having data? Wouldn''t you rather
simply undefined ''DataContainer<void>''? I mean, declare it but don''t
provide the definition...



[snip]


我遇到了最近:我为标记图表实现了一个类模板


template< typename VertexLabel,typename EdgeLabel>

类图{

...

};


在某处你会有节点类型,比如


struct vertex_node {

...

VertexLabel the_label;

...

};


现在,考虑未标记的图表或具有
$ b的图表是完全合理的$ b只有顶点的标签。在这种情况下,您希望能够传递没有值作为模板参数的

类型。因此,我定义了很多像b一样的b $ b,


struct empty {};


和程序优雅地处理诸如图形< empty,int>之类的东西。

到OP:事实证明,如果你使一个空类更有用

它兼容使用标准容器类型和流。因此我实际上是

这样做了:


struct empty {};


std :: ostream&运营商LT;< (std :: ostream& ostr,empty const& e){

return(ostr<<''#'');

}


std :: istream&运营商GT;> (std :: istream& istr,empty& e){

char chr;

istr>> chr;

if(chr!=''#''){

istr.setstate(std :: ios_base :: failbit);

}

返回(istr);

}


bool运算符==(空a,空b){

返回(true);

}


bool operator!=(空a,空b){

返回(false);

}


bool运算符< (空a,空b){

返回(假);

}


bool运算符< =(空a,空b){

返回(true);

}


bool运算符> (空a,空b){

返回(假);

}


bool运算符> =(空a,空b){

返回(true);

}

最佳


Kai-Uwe Bux


[snip]

I ran into that recently: I implemented a class template for labelled graphs

template < typename VertexLabel, typename EdgeLabel >
class graph {
...
};

Somewhere inside you would have node types like

struct vertex_node {
...
VertexLabel the_label;
...
};

Now, it makes perfect sense to consider graphs that are not labelled or have
only labels for the vertices. In that case, you want to be able to pass a
type that has no values as a template parameter. Thus, I defined, very much
like the OP,

struct empty {};

and the program gracefully deals with stuff like graph<empty,int>.
To the OP: It turns out, that an empty class is even more useful if you make
it compatible with standard container types and streams. Thus I actually
did this:

struct empty {};

std::ostream & operator<< ( std::ostream & ostr, empty const & e ) {
return( ostr << ''#'' );
}

std::istream & operator>> ( std::istream & istr, empty & e ) {
char chr;
istr >> chr;
if ( chr != ''#'' ) {
istr.setstate( std::ios_base::failbit );
}
return( istr );
}

bool operator== ( empty a, empty b ) {
return( true );
}

bool operator!= ( empty a, empty b ) {
return( false );
}

bool operator< ( empty a, empty b ) {
return( false );
}

bool operator<= ( empty a, empty b ) {
return( true );
}

bool operator> ( empty a, empty b ) {
return( false );
}

bool operator>= ( empty a, empty b ) {
return( true );
}
Best

Kai-Uwe Bux


Victor Bazarov写道:
Victor Bazarov wrote:
我想知道它的应用是什么?你会如何使用它?
我理解需要存储并获取它,并且具有
typedef等等,但是''Vertex< void>''的含义是什么? ?你从中得到了什么?


我已经用Boost Graph进行了几周的实验,而且它b / b
并不能完全适合我们的需求(它太难了

进行非平凡的扩展。因此我决定自己实现一个简单的,
但仍然有点普通的图表类。现在节点和边缘

可能包含数据项,但不是必需的。当使用较大的图形

时,你不会想要一些默认数据成员的开销。我也不希望
想要为空数据成员专门化整个图类;首先

所有因为它需要4个单独的组合,其次

保持单独的实施是很乏味的,而基础是

相同。我在这里简化了代码,使其在

新闻组中更具可读性。数据的外部属性映射方法比它解决的问题更多......因此内部数据是优选的。

我意识到基于模板具有不同的数据内容
参数是一种有效的方法(我已经看过如果没有写一些),
但是*有*数据的重点是什么?你不宁愿
只是未定义''DataContainer< void>''?我的意思是,声明它但不提供定义...
I am wondering what would be the application of it? How would you use it?
I understand the need to store something and get it back, and have the
typedef, and so on, but what would be the meaning of ''Vertex<void>''? What
use do you derive from it?
I''ve been experimenting with Boost Graph for some weeks now, and it
doesn''t quite suit our needs in a natural way (it''s too complicated to
make non-trivial extensions). Therefore I decided to implement a simple,
but still somewhat general graph class myself. Now the nodes and edges
may contain data items, but not neccesarily. When using larger graphs
you wouldn''t want the overhead of some default data member. I also don''t
want to specialize the entire graph class for empty data members; first
of all because it would require 4 seperate combinations, and secondly
it''s tedious to maintain seperate implementations while the basics are
the same. I simplified the code here to make it more readable in the
newsgroup. The external property map approach for data caused more
problems than it solved... so internal data is prefered.
I realise that having different data contents based on the template
argument is a valid approach (and I''ve seen if not written some of that),
but what would be the point of *not* having data? Wouldn''t you rather
simply undefined ''DataContainer<void>''? I mean, declare it but don''t
provide the definition...




这就是我想知道的 :有一种更简单的方法。经过一天的工作后,我倾向于超过
复杂的C ++代码...我不确定你在这里是什么意思?我确实希望人们真正使用Vertex< void>,它不仅仅是

a安全防范某人试图用void实例化类

作为模板参数。我确实有这种唠叨的感觉,我现在有一个多余的间接水平。有什么想法吗?


-

问候,


Ferdi Smit(M.Sc。)

电子邮件: Fe********@cwi.nl

房间:C0.07电话:4229

INS3可视化和3D界面

CWI荷兰阿姆斯特丹



That''s what I''m wondering about: is there an easier way. I tend to over
complicate C++ code after a day of work... I''m not exactly sure what you
mean here? I do want people to actually use Vertex<void>, it''s not just
a safe-guard against someone trying to instantiate the class with void
as a template argument. I do have the nagging feeling I''m having one
redundant level of indirection at the moment. Any thoughts?

--
Regards,

Ferdi Smit (M.Sc.)
Email: Fe********@cwi.nl
Room: C0.07 Phone: 4229
INS3 Visualization and 3D Interfaces
CWI Amsterdam, The Netherlands


这篇关于设计有一个可选的数据成员;这有什么好处吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆