Hatena::ブログ(Diary)

swwの日記 このページをアンテナに追加 RSSフィード

<<アーカイブ(過去の日記一覧)へ

2012-03-08 [C++]VS2008でauto_ptrをメンバ変数にもつクラスをvectorに入れる( このエントリーを含むブックマーク このエントリーのブックマークコメント

std::auto_ptr をメンバ変数に持つクラスを std::vector に入れたい、そんなことありますよね?

VS2010 ならば

#include "stdafx.h"
#include <memory>
#include <vector>

class A {};

class B {
private:
	std::auto_ptr<A> a_;
public:
	B( void ) : a_( new A() ) {}
};

int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<B> bs1;
	bs1.push_back( B() ); // Bのコピーコンストラクタでエラー

	std::vector<B> bs2;
	bs2 = bs1;            // ここもBのコピーコンストラクタでエラー

	return 0;
}

なんてコードで問題ありませんが、2008だと上記コメント部分でコンパイルエラーとなります

B( const B& other ) : a_( other.a_ ) {} // otherはconstなので所有権委譲ができない

B::a_ の型を std::tr1::shared_ptr にすることでこの問題は解決しますが、なにせ shared_ptr は重いし遅い。

※一般用途では shared_ptr で問題ないパフォーマンスです。ただ、インスタンスが数百万単位になると馬鹿にならない。

では boost::ptr_vector ならばどうなるかというと


#include "stdafx.h"
#include <memory>
#include <boost/ptr_container/ptr_vector.hpp>

class A {};

class B {
private:
	std::auto_ptr<A> a_;
public:
	B( void ) : a_( new A() ) {}
};

int _tmain(int argc, _TCHAR* argv[])
{
	boost::ptr_vector<B> bs1;
	bs1.push_back( new B() ); // ここは通る

	std::vector<B> bs2;
	bs2 = bs1;                // ここで B のコピーコンストラクタでエラー

	return 0;
}

ということになってしまいます。

ということで続きは明日

トラックバック - http://d.hatena.ne.jp/sww/20120308

2012-02-29

アプリケーション初期化処理でエラーが発生しました。 23:49 アプリケーションの初期化処理でエラーが発生しました。を含むブックマーク アプリケーションの初期化処理でエラーが発生しました。のブックマークコメント

ということで、今作っているアプリC++/CLI のプロジェクトを追加し、libやらを設定した後に起動すると「アプリケーション初期化処理でエラーが発生しました。エラーコード 0xC0000005」というのが発生。

起動時のdll読み込み処理などを見てみると、エラー発生直前と思えるのに comctl32.dll があり、それが SxS で入るdllだったのでバージョン違いか何かか?と想像。

ネットをたどると sxstrace.exe を使うと良いというのがあったので探してみると・・・無い。無い。無い。


なんと Vista 以降にしか入っていないと言うではないか(開発はXP SP3)。

しょうが無いので Vista なら sxstrace で何か解るかと思って実験してみると今度は出ない。

意味がわからない・・・

ということで、あきらめて SVN から新規に co して同等のを作ってみると今度は起動できる。

いったい何が悪かったのか両方を見比べてみると。dllのロード順が違う。同じソリューションの他のライブラリの方が先にロードされている。

両方の exe プロジェクトのリンカ設定を見ると lib の順番が違う。

一応替えてみると今度は上手くいく。

うーんこれはそういうものなのか、向こうのライブラリが悪いのか・・・

とりあえずそんなところで今日は終了。

swwsww 2012/02/29 23:52 ちなみに環境は
OS:XP SP3
VS:2008 SP2
exeのMFC:静的リンク

swwsww 2012/03/02 00:01 結局治って無かった……
明日がむばる

swwsww 2012/03/08 23:52 色々見てみたがやっぱりリンカ順番でどうにかなった。
気持ち悪いーー

トラックバック - http://d.hatena.ne.jp/sww/20120229

2012-02-24

[] MSXML の SAXWriter 00:32  MSXML の SAXWriterを含むブックマーク  MSXML の SAXWriterのブックマークコメント

Domを使って書き込むのではなく、SAXで何か良いのはないかと思っていたら

MSXMLに IMXWriter という SAXWriter があるではないか。

今のコードは Windows 限定だし使ってみるかーということでトライ。


// saxwritertest.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include "windows.h"
#include "Objbase.h"
#import <msxml6.dll> named_guids

#include <iostream>
#include <vector>

namespace {

bool CreateStream( IStream** stream ) {
	HRESULT hr = ::CreateStreamOnHGlobal( NULL, TRUE, stream );
	return hr == S_OK;
}

} // namespace


int _tmain(int argc, _TCHAR* argv[])
{
	::CoInitialize( NULL );

	IStreamPtr stream;
	CreateStream( &stream.GetInterfacePtr() );

	try {
		MSXML2::IMXWriterPtr writer;
		HRESULT hr = writer.CreateInstance( MSXML2::CLSID_MXXMLWriter60 );
		writer->byteOrderMark = VARIANT_TRUE;
		writer->encoding	= _bstr_t( "utf-8" );
		writer->indent		= VARIANT_TRUE;
		writer->output		= stream.GetInterfacePtr();

		MSXML2::ISAXContentHandlerPtr handler = writer;
		handler->startDocument();

		wchar_t* ns( L"test" );
		wchar_t* local( L"example" );
		wchar_t* qname( L"test:example" );
		handler->startElement(
			reinterpret_cast<unsigned short*>( ns ), wcslen( ns ),
			reinterpret_cast<unsigned short*>( local ), wcslen( local ),
			reinterpret_cast<unsigned short*>( qname ), wcslen( qname ),
			NULL );

		handler->endElement(
			reinterpret_cast<unsigned short*>( ns ), wcslen( ns ),
			reinterpret_cast<unsigned short*>( local ), wcslen( local ),
			reinterpret_cast<unsigned short*>( qname ), wcslen( qname )
			);
		handler->endDocument();

	}catch(_com_error& e ){
		std::cout << e.ErrorMessage() << std::endl;
		::CoUninitialize();
		return 0;
	}

	{ // 書き込み内容を見る
		LARGE_INTEGER pos = {0, 0};
		stream->Seek( pos, STREAM_SEEK_SET, NULL );

		size_t size( 1024 );
		std::vector<byte> buffer;
		buffer.resize( size, 0 );
		unsigned long read;
	 	stream->Read( &buffer[0], size, &read );
		std::cout << &buffer[0] << std::endl;
	}

	::CoUninitialize();
	return 0;
}

で結果が

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<test:example/>
続行するには何かキーを押してください . . .

・・・おーい? xmlns が出てないよ?

と思ってネットを探っていたら バグです とか・・・

あきらめて、litexml とか xerces とか libxml とか使いましょ!

トラックバック - http://d.hatena.ne.jp/sww/20120224

2012-02-23

日記 23:15 日記を含むブックマーク 日記のブックマークコメント

久々に!日記を!書く!

トラックバック - http://d.hatena.ne.jp/sww/20120223

2009-08-04

[][]ファクトリの取得方法 15:42 ファクトリの取得方法を含むブックマーク ファクトリの取得方法のブックマークコメント

うーんC++で下のようなコードの書き方がわからん・・・

import java.util.Map;

public abstract class Base {
    static Map<String, Factory> map;
    static {
        map.put("foo", new Foo.FooFactory());
        map.put("bar", new Bar.BarFactory());
    }
    
    static Base create(String target) {
        for (Map.Entry<String, Factory> entry : Base.map.entrySet()) {
            if (target.equals(entry.getKey())) {
                return entry.getValue().create();
            }
        }
        return null;
    }
    
    public abstract String getType();
}


interface Factory {
    Base create();
}

class Foo extends Base {
    static class FooFactory implements Factory {
        public Foo create() {
            return new Foo();
        }
    }
    
    public String getType() {
        return "foo";
    };
}

class Bar extends Base {
    static class BarFactory implements Factory {
        public Bar create() {
            return new Bar();
        }
    }
    
    public String getType() {
        return "bar";
    };
}

class Main {
    public static void main(String[] args) {
        Base base = Base.create("bar");
        System.out.println(base.getType());
    }
}

bleis-tiftbleis-tift 2009/08/05 18:31 できる限り元の Java コードに似せて作ってみました。
http://codepad.org/ZOquIYhp

トラックバック - http://d.hatena.ne.jp/sww/20090804