2007年1月25日
#
今天在项目中使用了C++的proper模板类,这个模板类是用来完成其它支持属性的语言关键字“属性”类似作用的。
在我的代码库内收藏了Achilleas Margaritis编写的C++ object properties library。很吸引人而且实用的功能。可惜在我的VS2005中使用时发生了以下两个错误,错误经定位后均出现在property.hpp中:
1、 出错代码:
typedef _property1<C, T>::_property2<A, S> base_class;
错误提示:
warning C4346: “cpp::properties::_property1<C,T>::_property2<A,S>”: 依赖名称不是类型,用“typename”为前缀来表示类型;
2、 出错代码:
class interface {};
错误提示:
error C2332: “class”: 缺少标记名;
*********************************************************
问题1很快查到原因:
*********************************************************
作者:Scott Meyers
译者:fatalerror99 (iTePub's Nirvana)
nested dependent name(嵌套依赖名字)会导致解析困难。例如,假设我们更加愚蠢地
以这种方法开始 print2nd:
template<typename C>
void print2nd(const C& container)
{
C::const_iterator * x;
...
}
这看上去好像是我们将 x 声明为一个指向 C::const_iterator 的 local variable(局
部变量)。但是它看上去如此仅仅是因为我们知道 C::const_iterator 是一个 type(
类型)。但是如果 C::const_iterator 不是一个 type(类型)呢?如果 C 有一个 st
atic data member(静态数据成员)碰巧就叫做 const_iterator 呢?再如果 x 碰巧是
一个 global variable(全局变量)的名字呢?在这种情况下,上面的代码就不是声明
一个 local variable(局部变量),而是成为 C::const_iterator 乘以 x!当然,这
听起来有些愚蠢,但它是可能的,而编写 C++ 解析器的人必须考虑所有可能的输入,甚
至是愚蠢的。
直到 C 成为已知之前,没有任何办法知道 C::const_iterator 到底是不是一个 type(
类型),而当 template(模板)print2nd 被解析的时候,C 还不是已知的。C++ 有一
条规则解决这个歧义:如果解析器在一个 template(模板)中遇到一个 nested depen
dent name(嵌套依赖名字),它假定那个名字不是一个 type(类型),除非你用其它
方式告诉它。缺省情况下,nested dependent name(嵌套依赖名字)不是 types(类型
)。(对于这条规则有一个例外,我待会儿告诉你。)
知道原因就简单了,直接把代码修正为:
typedef typename _property1<C, T>::_property2<A, S> base_class;
问题解决(只能说在Windows平台下VS自带的C++编译器问题解决,其它编译器甚至其它平台上的编译器我可没有去试过)。
*********************************************************
问题2我没查到原因,因为我直接按控制台项目创建示例代码时没出现这样的错误,而在Win32项目创建项目示例代码时就出现这样的报错。因为我大胆猜测,应当VS2005其自带的C++编译器为了支持C++/CLI,将interface列为关键字的缘故。因此编译器认为class interface是两个关键字的罗列,所以才会报“缺少标记名”。所以我的做法如下:
*********************************************************
把property.hpp(就是那个实现property模板类的文件)中所有涉及“interface”的地方完全替换为“_interface”,同时为保持风格统一,将property模板类中所有作用相同的类全修改为下划线开头!(_variable/_read_write/_read_only/_write_only),问题搞定!
不知道Achilleas Margaritis看到了我的解决方案是不是哭笑不得,哈哈~~
2006年11月16日
#
2006年8月10日
#
tokenizer - Break of a string or other character sequence into a series of tokens, from John Bandela
tokenizer - 分解字串,提取内容.作者: John Bandela
例一:
// simple_example_1.cpp
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>
int main(){
using namespace std;
using namespace boost;
string s = "This is, a test";
tokenizer<> tok(s);
for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}
输出
This
is
a
test
tokenizer默认将单词以空格和标点为边界分开.
例二:
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>
int main(){
using namespace std;
using namespace boost;
string s = "Field 1,\"putting quotes around fields, allows commas\",Field 3";
tokenizer<escaped_list_separator<char> > tok(s);
for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}
输出
Field 1
putting quotes around fields, allows commas
Field 3
双引号之间可以有标点.
例三:
// simple_example_3.cpp
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>
int main(){
using namespace std;
using namespace boost;
string s = "12252001";
int offsets[] = {2,2,4};
offset_separator f(offsets, offsets+3);
tokenizer<offset_separator> tok(s,f);
for(tokenizer<offset_separator>::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}
把12252001分解为
12
25
2001
例4:
// char_sep_example_1.cpp
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>
int main()
{
std::string str = ";!!;Hello|world||-foo--bar;yow;baz|";
typedef boost::tokenizer<boost::char_separator<char> >
tokenizer;
boost::char_separator<char> sep("-;|");
tokenizer tokens(str, sep);
for (tokenizer::iterator tok_iter = tokens.begin();
tok_iter != tokens.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
std::cout << "\n";
return EXIT_SUCCESS;
}
输出
<!!> <Hello> <world> <foo> <bar> <yow> <baz>
自定义分隔的标点
例5:
// char_sep_example_2.cpp
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>
int main()
{
std::string str = ";;Hello|world||-foo--bar;yow;baz|";
typedef boost::tokenizer<boost::char_separator<char> >
tokenizer;
boost::char_separator<char> sep("-;", "|", boost::keep_empty_tokens);
tokenizer tokens(str, sep);
for (tokenizer::iterator tok_iter = tokens.begin();
tok_iter != tokens.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
std::cout << "\n";
return EXIT_SUCCESS;
}
The output is:
<> <> <Hello> <|> <world> <|> <> <|> <> <foo> <> <bar> <yow> <baz> <|> <>
去除-; , 保留|但将它看作是分隔符,当两个分隔符相邻的时候会自动加空格
例6:
// char_sep_example_3.cpp
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>
int main()
{
std::string str = "This is, a test";
typedef boost::tokenizer<boost::char_separator<char> > Tok;
boost::char_separator<char> sep; // default constructed
Tok tok(str, sep);
for(Tok::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
std::cout << "\n";
return EXIT_SUCCESS;
}
The output is:
<This> <is> <,> <a> <test>
保留标点但将它看作分隔符
Examples of fixed-width encoding forms:
Type |
Each character encoded as |
Notes |
7-bit |
a single 7-bit quantity |
example: ISO 646 |
8-bit G0/G1 |
a single 8-bit quantity |
with constraints on use of C0 and C1 spaces |
8-bit |
a single 8-bit quantity |
with no constraints on use of C1 space |
8-bit EBCDIC |
a single 8-bit quantity |
with the EBCDIC conventions rather than ASCII conventions |
16-bit (UCS-2) |
a single 16-bit quantity |
within a code space of 0..FFFF |
32-bit (UCS-4) |
a single 32-bit quantity |
within a code space 0..7FFFFFFF |
32-bit (UTF-32) |
a single 32-bit quantity |
within a code space of 0..10FFFF |
16-bit DBCS process code |
a single 16-bit quantity |
example: UNIX widechar implementations of Asian CCS's |
32-bit DBCS process code |
a single 32-bit quantity |
example: UNIX widechar implementations of Asian CCS's |
DBCS Host |
two 8-bit quantities |
following IBM host conventions |
Examples of variable-width encoding forms:
Name |
Characters are encoded as |
Notes |
UTF-8 |
a mix of one to four 8-bit code units in Unicode and one to six code units in 10646 |
used only with Unicode/10646 |
UTF-16 |
a mix of one to two 16 bit code units |
used only with Unicode/10646 |
Boost中提供了一个UTF-8 Codecvt Facet,可以在utf8和UCS-4(Unicode-32)之间转换.
使用方式如下
//...
// My encoding type
typedef wchar_t ucs4_t;
std::locale old_locale;
std::locale utf8_locale(old_locale,new utf8_codecvt_facet<ucs4_t>);
// Set a New global locale
std::locale::global(utf8_locale);
// UCS-4 转换为 UTF-8
{
std::wofstream ofs("data.ucd");
ofs.imbue(utf8_locale);
std::copy(ucs4_data.begin(),ucs4_data.end(),
std::ostream_iterator<ucs4_t,ucs4_t>(ofs));
}
// 读入 UTF-8 ,转换为 UCS-4
std::vector<ucs4_t> from_file;
{
std::wifstream ifs("data.ucd");
ifs.imbue(utf8_locale);
ucs4_t item = 0;
while (ifs >> item) from_file.push_back(item);
}
//...
UTF-8 Codecvt Facet详见
http://www.boost.org/libs/serialization/doc/codecvt.html
2006年8月1日
#
系统在VC7.1下开发,一直没问题,最近升级到VC8,然后重新编译,报如下错误:
d:\program files\microsoft visual studio 8\vc\atlmfc\include\atlplus.h(647) : error C2065: 'CStringW' : undeclared identifier
d:\program files\microsoft visual studio 8\vc\atlmfc\include\atlplus.h(647) : error C2146: syntax error : missing ';' before identifier 'strW'
d:\program files\microsoft visual studio 8\vc\atlmfc\include\atlplus.h(647) : error C3861: 'strW': identifier not found
但是在atlplus.h中明明已经include过atlstr.h:
...
#include <shellapi.h>
#include "atlevent.h"
#include <cstringt.h>
#include <atlstr.h>
//Avoid using <atlstr.h> except in the registry templates (for circular dependencies).
[
provider(name="ATL4", uuid="BC6B4B8A-0E4A-4bc9-B319-9DC2ACFB61EE")
];
...
...
GetStringAtLoc(rgStrings, dwValue, rgBytes, &szReplacement);
CStringW strW(szReplacement ? szReplacement : rgBytes.m_aT); // 在该行报错
...
已经查了很久,没有解决办法,请问有朋友遇到过类似的情况没有,最后如何解决的?
======================
问题暂时解决,办法如下:
1、在atlplus.h中,用<stdstring.h>代替<atlstr.h>:
(stdstring.h是Joe O'Leary编写的用于取代完整取代CString的类,基于std::string)
#include <stdstring.h>
2、修改报错行:
CStringW strW(szReplacement ? szReplacement : rgBytes.m_aT); // 在该行报错
修改为:
CStdStringW strW(szReplacement ? szReplacement : rgBytes.m_aT); // 该行通过
现在编译已通过,但由于我改变了系统文件<atlplus.h>的内容,给atl额外引入了stl的负担,会影响atl完整性和高效性。该解决办法是很不恰当的。
还请各位高人给出合适的解决办法,谢谢。
2006年6月22日
#
我写了一个程序,每N秒,定时对数据库进行刷新,以修正数据库内的一些数据。我把它放在启动菜单栏里,希望一开机就运行。同时希望程序一运行就隐藏到系统栏,这样不影响我使用其它程序。
本来我是想直接在CMainDlg::OnInitDialog中用ShowWindow(SW_HIDE);的,但是很不幸,程序窗口依然显示。在网上查找一段时间以后没有找到解决办法,只好自行摸索了。
最后我是通过延时发隐藏窗口请求来解决的(先显示窗口,等待一段时间,再隐藏窗口)。我想主窗口在CMainDlg::OnInitDialog中不能隐藏的原因,是该函数运行后,还有一些事件刷新了主窗口,所以我通过延时等待所有的主窗口事件处理完成以后再进行隐藏。
在CMainDlg::OnInitDialog中:
//
设置定时间隔
SetTimer(IDT_TIMER_TOSYSTRAY,DELAY_TIME
*
1000
);
在CMainDlg::OnTimer中:
switch(wParam)
{
case IDT_TIMER_TOSYSTRAY:
// 隐藏窗口到系统栏
KillTimer(IDT_TIMER_TOSYSTRAY);
SendMessage(WM_CLOSE);
break;
case IDT_TIMER_REFRESH:
break;
}
真正的处理函数:
LRESULT CMainDlg::OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// TODO: Add your message handler code here and/or call default
if (IsWindowVisible())
ShowWindow(SW_HIDE);
return 0;
}
2006年6月16日
#
我在公司的文件服务器上起了IIS 6 Web服务,在某目录内放置了.TAB文件(超级报表格式),但是用浏览器下载文件的时候报错,无法下载。
进入文件服务器上的IIS 管理器,右击“网站”==>“网站属性”,选择“http头”,再选择“MIME类型” ==> “新建”
==>“扩展名”:.tab(注意,tab前面有点)==>“MIME类型”:application/ChinaExcel
问题解决,在客户端可以下载文件,如果客户端安装了ChanaExcel程序,则可以通过IE直接打开文件。
原因:
见IIS6 属性页上的“MIME”描述:IIS只为扩展名在MIME类型列表中注册了的文件提供服务。.TAB为非标准文件后缀名,因此需要在IIS中进行注册,IIS对未注册文件不予处理。
2005年10月10日
#
这些天来研究XML的各类应用。前天花了近一天的时间来研究SVG图形文件格式。发现这个规范的确很好,如果研究好了,以后就应用在项目上,应该很酷的。
不过试验的时候,老是中文无法显示,搞得我灰头灰脸的。都怀疑我是不是弱智了。
按以前处理xml文件的经验,我先把语言编码加入SVG。呵呵,这里犯了一个错误,因此我的xmlWriter认为不是良好格式文档。原来是顺序声明错误啦。
<?xml version="1.0" standalone="no" encodeing="GB2312" ?>,能看出来哪儿错了吗,原来应当写成
<?xml version="1.0"
encodeing="GB2312" standalone="no" ?>,晕,没细看标准的代价,害得我在网上查来查去。
但是这样还是不能显示中文,再晕~~~~~~~~~~,再去网上查~~~~~~~~,哈哈,原来有人也遇到过这个问题哟,网上牛人蛮多呀,前辈哟,看看eureka的心得(
http://www.ee-studio.com/drupal/node/447/print):
好多SVG编辑器都有不能正常支持中文,后来自己手工创建SVG文件,却也不能在浏览器插件里正常显示。还以为是插件问题(如adobe svg viewer和corel svg viewer等),象我用inkscape,就能很好的处理中文,但却不能在浏览器里正常显示!不知为什么,还真以为插件问题。查看svg viewer的技术规范,都说是支持utf-8的,那是什么问题呢?难道是文字编码问题,后来几经测试,用各种编码及encoding头,还是不对劲。
后来我好不容易总算琢磨出问题所在,原来你必须给中文加上中文字体。看来adbobe svg viewer和corel svg viewer缺省都没有带支持某种中文字体的,不象inkscape,能正常显示中文。因此,在这种情况下,给中文加上某种字体的样式,就可以正常显示而不是一些框框了,包括从W3C来的一些SVG中文幻灯片,给它加上中文某中字体的样式才行!
不过我用的编辑器里,webdraw 和 xstudio还是不支持中文的!不能很好的处理,只有inkscape,能很好的支持中文。但它不带有原生的SVG代码编辑,其xml editor是对节点进行编辑的,不能对原文件进行编辑。呵呵,事物总是不断发展吧。
哈哈,这不正是我要的吗,试试去喽。感谢eureka!
2005年9月22日
#
2005年9月14日
#
从上周开始,我开始将以前自己所做的Res3项目转化成UNICODE格式。
这个做法的动力来源有两个:
一个就是人云亦云啦,看到不少文章中都说了UNICODE编码的好处,也有些心动。
第二个原因是,我对目前开发的整个项目的远景构想,是想把这个项目拆解成很多小的部分。使得这些小的项目资源可以提供给以后其它的项目使用。每个部分不管是对内还是对外的接口,都尽量依据现有的标准来开发完成。例如UNICODE、WebService、XML等等。
这次是我所做的一个小试验,来验证自己的想法是否可行,真是不做不知道,原先我认为将现有的代码转换成支持UNICODE,应当是一件很容易的事情。做起来才晓得,由于自己以前完全没有考虑过这种转换,很多遗留的代码,比如文字常量,都要手工进行转换。也许以后,我应当写出一个小的转换程序,用来辅助完成任务。
还有一个困难,就是我以前经常使用的开源代码,很多代码也是没有考虑到到UNICODE编码,这种情况下,我要么对源代码进行了修改,要么就换用了其它支持UNICODE的开源代码。好可惜哟,有些代码在ANSI下很好用的,现在只好放弃。
这次UNICODE转换试验完成后,会有很多心得,我会再整理记录下来,免得以后再走弯路。