Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コピーされずに呼出し元の一時オブジェクトとなる返却値

タグ: C++ VS2005 gcc
struct Base { void func() const; };

// コピー不可
struct A : Base
{
	A(int n);

private:
	A(const A&);
};

// 右辺値のコピー不可
struct B : Base
{
	B(int n);
	B(B&);
};

// コピー可
struct C : Base
{
	C(int n);
	C(const B&);
};

const A A1() { return 1; }
const A A2() { return A(2); }
const B B1() { return 1; }
const B B2() { return B(2); }
const C C1() { return 1; }
const C C2() { return C(2); }

int main(int, char*[])
{
	A1().func();
	A2().func();
	B1().func();
	B2().func();
	C1().func();
	C2().func();
	return 0;
}
  • gcc 4.0.1 のコンパイルエラー

     In function ‘const A A1()’:
    9: error: ‘A::A(const A&)’ is private
    26: error: within this context
    9: error: ‘A::A(const A&)’ is private
    26: error: within this context
    26: error:   initializing temporary from result of ‘A::A(int)’
     In function ‘const A A2()’:
    9: error: ‘A::A(const A&)’ is private
    27: error: within this context
    9: error: ‘A::A(const A&)’ is private
    27: error: within this context
     In function ‘const B B1()’:
    28: error: no matching function for call to ‘B::B(const B)’
    16: note: candidates are: B::B(B&)
    15: note:                 B::B(int)
    28: error:   initializing temporary from result of ‘B::B(int)’
     In function ‘const B B2()’:
    29: error: no matching function for call to ‘B::B(B)’
    16: note: candidates are: B::B(B&)
    15: note:                 B::B(int)
  • VC8 のコンパイルエラー

    (27) : error C2248: 'A::A' : private メンバ (クラス 'A' で宣言されている) にアクセスできません。
            (9) : 'A::A' の宣言を確認してください。
            (4) : 'A' の宣言を確認してください。
    (29) : warning C4239: 非標準の拡張機能が使用されています : '引数' : 'B' から 'B &' への変換です。
            非定数の参照は左辺値へのみバインドされます。コピー コンストラクタで非定数への参照を指定できます。

A1() B1() は gcc 4.0.1 ではコンパイルエラーとなるが、 VC8 では通る。
普通に考えれば、これらは A2() B2() と同じ値を返すのだから、動作に違いが出るとは思えない。

『JIS X 3014:2003』6.6.3/2 return文

void でない型の《式》を持つ return 文は、値を返す関数でだけ使うことができ、その《式》の値が関数の呼出し元に渡される。 その《式》は、それが現れる関数の返却値の型に、暗黙に変換される。 return 文は、一時的オブジェクトの構築(12.2)及びコピーを伴うことがある。

メンバ関数 func() を呼ぶため、呼び出し元には関数の返却値をコピーした一時オブジェクトが生成される。
その際、RVO(戻り値最適化)が働いてコピーコンストラクタが呼ばれなかったとしても、関数が返す値をコピーするためのコピーコンストラクタは定義されていなければならない。

『JIS X 3014:2003』12.2/1 一時オブジェクト

一時オブジェクトの生成が避けられる場合(12.8)であっても、すべての意味規則上の制約は、一時オブジェクトが生成されたかのように遵守しなければならない。
コピーコンストラクタを呼び出さない場合であっても、アクセス可能性(11.)などのすべての意味規則の制約が満たされなければならない。

『JIS X 3014:2003』12.8/15 クラスオブジェクトのコピー

処理系は、ある基準が満たされれば、そのクラスオブジェクトのコピーによる構築を省略してよい。 これは、このオブジェクトのコピーコンストラクタ及び/又はデストラクタが副作用をもつ場合も含む。

よって、コピーコンストラクタを呼び出せない A1() B1() はコンパイルエラーにならなければならない……はず。
見方によっては、コピーを伴うことがあるという文は本当に(RVOとかいうレベルではなく)コピーしなくてもいいようにも思えるが……

まあなんにせよ、「暗黙の型変換で返したときだけ通る」とか不気味だし。
素直にこれは「通らない」ものと考えておこう。

続々・Safari RSSリーダの不調

タグ: Mac Safari

フィードの更新が通知されなくなるのは PubSubAgent が落ちるからのような気がしていたが、別にそんなことはなかった。
落ちなくても通知されなくなることはある。
この状態になった場合、手動で PubSubAgent を落として再起動させるしかない。
潔く落ちてくれれば、フィードを読むだけで再起動させられるからまだ楽なのに。

もういっそ、 cronで定期的に強制再起動させてやろうか……

Safari 3.1

タグ: Mac Safari

一週間で直るなんて/(^o^)\

03月18日のココロ日記(BlogPet)

放課後、難しい表現さんと文について熱く語り合いました。むいさんのひみつも聞いちゃいました……!

*このエントリは、ブログペットのココロが書いてます♪

ニコニコ動画の選ぶ道

ニコ動がテレビ局に宣言「番組の著作権侵害動画はすべて削除します」 - INTERNET Watch

ドワンゴは11日、同社子会社のニワンゴが運営する「ニコニコ動画」における著作権侵害動画への対応策を発表した。1)既存の著作権侵害放送番組動画はすべて削除すること、2)新規投稿動画の監視を行ない、著作権侵害放送番組動画については直ちに削除すること──の2点を示した申し入れ書を、テレビ局6社に提出したという

ニワンゴが先手を打つとは、ちょっと思っていなかった。
もちろん、先手を取れるに越したことはないので、それはとても良いことなのだが。

ニワンゴ代表取締役の杉本氏は、『偽・うpのギョーカイ時事放談SUPER! 第17回放送』で 僕らは違法的に上げられた動画を扱う権利を持っていない。権利者からの申告がなければ(それが本当に権利者の許可を得ずに上げられたものであるとは断定できないため)消すことができない と語っていた。
今回の申し入れは、これを解決するためのもの。
放送局に対し、「著作権を守るため、御社が権利を有すると判別できるコンテンツに関しては、御社の判断を得ることなく削除します」と宣言したわけだ。

そしてまた、これはコンテンツ所有者への語りかけでもある。

ニコニコ動画はもう放送番組動画を扱うことが出来ない。
そのため、放送番組に関しては、MAD等によって盛り上げていくことが出来ない。
我々はこの1年、ニコニコ動画でのコンテンツ配信に関し、放送番組を利用してプロモーションを行ってきた(:p)
この結果を見た上で、もし、我々のシステムを利用した方が、テレビで放送するよりも多くの利益を見込めると判断できたならば、是非こちらでの配信を考えて欲しい――

これによって、コンテンツ所有者がニコニコ動画に集まるようであればニワンゴの勝ち。
たとえ集まらなくても、危険管理上解決しておかなければならない事項なので問題はない。

あとは、削除体制がどう変わるかだが……

今回の“宣言”を機に一斉にテレビ番組動画の削除を開始するわけではないとしている。また、特にこのタイミングでシステムや監視体制を増強し、テレビ番組の著作権侵害動画を完全に排除する仕組みが実現されたということでもないという。

変わんないのかよ( ゚Д゚)

となると、結構緩いのかな。
今回の申し入れは「放送番組」に限定しているから、放送以外の映像ソースが存在する(DVDとか)場合は消せないとか。

CNETの記事では

対象となるのは放送番組をそのまま掲載したもののほか、MADと呼ばれる加工作品も含まれる。

とあるが、これもどの辺の加工まで削除するつもりなのやら。
キャラクターだけ切り抜いて利用しているものも消すとなると、私の好きな作品も大分消えてしまうことになるなぁ。
まあ、仕方のないことだけど……

03月11日のココロ日記(BlogPet)

むいさんと、なんとなく心が通じたかも……そんな気がしました。

*このエントリは、ブログペットのココロが書いてます♪

SafariのRegExp

タグ: Mac Safari JavaScript

このBlogのコードの大半は、SyntaxHighlighter によって動的に色付けされる(JavaScriptが有効な場合)。
ところがこの色付け、何故かSafariでは思った通りにならないことがある。

例えばこのコード。

/**
 * hogehoge
 */
// hogehoge
/**
 * ほげほげ
 */
// ほげほげ

Firefox 2.0.0.12 ではこのように表示される。
Firefox

しかし Safari 3.0.4 だと
Safari
日本語を含むC言語形式のコメントが色付けされない

SyntaxHighlighter におけるC言語形式コメントの正規条件は以下の通り。

MultiLineCComments : new RegExp('/\\*[\\s\\S]*?\\*/', 'gm'),

Safariの RegExp\S を日本語にマッチさせないのだろうか?
いくつかパターンを立てて検証してみる。

str ="/*ABCあいう*/";
document.write(str.match('/\\*[\\s\\S]*?\\*/','gm') + '<br />');
document.write(str.match('/\\*[\\S]*?\\*/','gm') + '<br />');
document.write(str.match('/\\*\\S*?\\*/','gm') + '<br />');
document.write(str.match('/\\*[ういあ\\S]*?\\*/','gm') + '<br />');
document.write(str.match('/\\*[うい\\S]*?\\*/','gm') + '<br />');
document.write(str.match('/\\*\\D*?\\*/','gm') + '<br />');
document.write(str.match('/\\*[ういあ\\D]*?\\*/','gm') + '<br />');
document.write(str.match('/\\*[うい\\D]*?\\*/','gm') + '<br />');

せっかくなので、今回はここ(↓)にスクリプトを埋め込んでおこう。



どうだろう。
「/*ABCあいう*/」が8行続いただろうか。

Safari 3.0.4 の結果はこうだった。


null
null
/*ABCあいう*/
/*ABCあいう*/
null
/*ABCあいう*/
/*ABCあいう*/
null


この結果から考えるに、どうやら Safari 3.0.4 では、「 [] の中のエスケープシーケンスは日本語にマッチングしない」ようだ。

IE7で自分のBlogを見る

タグ: 酷いコード

Safariで見ているだけでは分からないこと、多いね。

1行の整形済みテキストに横スクロールバーが付くとこの上なく見辛いのは、そもそも1行のテキストに整形済みの指定を入れるなということだろうか。
私は「“1行以上”のコードは全て整形済み」と考えているので、特に問題とは思わないのだが。

AWS用のインラインフレームで背景色を指定していなかったのは迂闊。
SafariでもFirefox(は記憶が定かではないが)でも、親フレームの背景色が引き継がれていたから、そういうものかと思っていた。

いくつか見付かった閉じていないタグも、Safariでは問題が顕在化しないから気付かなかった。
IE7で見ると、タグ一覧で改行が発生せず、記事本文の側まで溢れ出ていたり、文字が大きくなったまま戻っていなかったり(『らき☆すたオンライン』のつかさと同レベル)と、結構酷いことになっているのだが。
そんな状態で酷いコードとか書いても、説得力ないよ(ノ∀`)

とりあえず、目に付いた問題は、整形済みテキストのスクロールバー以外は直した。
ほかにも、そもそもこのBlogのテンプレートはHTML 4.01仕様なのに、記事の中にはXHTMLの文法が混ざっているという問題が存在がするのだが、その辺は諦め気味。
しかしまあ、せめてタグの閉じ忘れくらいは、上げる前にコードチェックを通して防ぐようにしよう……

Boost本メモ

タグ: C++ Boost

『Boost C++ Libraries 第2版』8.11 unit_test p640

BOOST_CHECK_PREDICATE( pred, arity, args )

これは Boost 1.32 までの仕様。
1.33 以降は args のデータ構造が Tuples から Sequences に変わり、

BOOST_CHECK_PREDICATE( pred, args )

となっている。
隣のページの BOOST_REQUIRE_PREDICATE も同じ。

続・Safari RSSリーダの不調

タグ: Mac Leopard

以前書いたSafariのRSSリーダが更新を通知してくれない件、なんとなく原因が分かった。
更新量が多いからか何か知らないが、スリープ解除後しばらくして PubSubAgent が落ちているのだ。

PubSubAgent は、例えばアクティビティモニタからプロセスを「終了」させた場合、勝手に再起動する。
しかしそこで「強制終了」を選ぶと、フィードを開くか、 PubSubAgent を使うアプリケーション(Safari、Mail、Xcode)を再起動するまで落ちっぱなしになる(でも再起動しても復帰しないことも……)。
今回の落ち方は強制終了に相当するため、以降 PubSubAgent が再起動されるまで、更新の通知は行われなくなってしまうのである。

これを解決するには、まず PubSubAgent が落ちないようにしなければならないのだが、正直、それは如何ともし難い。
なので、対症療法的ではあるが、定期的に PubSubAgent が起動するようなアクションを取ることで、ずっと落ちっぱなしになることを避けることにする。

本日見かけた酷いバグ

タグ: C++ gcc
#include <iostream>
#include <algorithm>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/lambda/lambda.hpp>

using namespace std;
using namespace boost;
using namespace boost::lambda;

void hoge(int n, const unsigned int array[])
{
	// 0 から n までの値を返すイテレータ
	const counting_iterator<unsigned int>
		it_first(0), it_last(n);

	// array[0] から array[n-1] の中で
	// 0 以外の値を得られる配列番号を求める
	// 全て 0 の場合は n を指す
	const counting_iterator<unsigned int>
		it(find_if(it_first, it_last, constant(array)[_1]));

	cout << *it << endl;
}

int main(int argc, char* argv[])
{
	const unsigned int array[32] = { 0 }; // 配列をゼロ初期化
	const unsigned int n = argc - 1; // 引数無しなら 0
	cout << n << endl;
	hoge(n, array);
	return 0;
}
  • gcc 3.2.3 で -O2 ビルドした場合の結果
    0
    0
    
  • gcc 3.2.3 で -O3 ビルドした場合の結果
    0
    32
    

-O3 ビルドしたものを gdb で見たところ、 it_last は正しく初期化されているものの、 find_if の第2引数が有り得ないことになっていた。
最適化のバグ、なんだろうなぁ。

@tparam (Doxygen 1.5.5)

タグ: C++ Doxygen

いつの間にか Doxygen 1.5.5 が出ていたので追加要素を眺めていたら……

id 153376: Added support for the \tparam command, which works similar to \param but is meant for documenting template parameters.

ずっと欲しいと思っていた「テンプレート引数コマンド」が実装されていた!

これまで、テンプレート引数の説明は、ユーザ定義パラグラフを使って

/**
 * @par テンプレート引数:
 * - <em>T</em> - なんかの型
 */
template <typename T>

こんな風に書いてきた。

しかし 1.5.5 からは、関数の仮引数宜しく

/**
 * @tparam T なんかの型
 */
template <typename T>

こう書ける。

ただし、関数引数に対して使える以下の記法は、テンプレート引数では使用できない。

template <
	typename T ///< なんかの型
>

テンプレート引数の方が、関数引数よりもこの記法が向いている(関数引数では入出力属性を記述できなくなる)だけに、ちょっと残念だ。

リテラル整数の型は何か

タグ: C++ gcc
#define HOGE 0x80000000

この時 HOGE は

  • int型の -2147483648
  • unsigned int型の 2147483648

のどちらになるか。

『JISX3014:2003』は、整数リテラルの型を以下の様に定めている。

整数接尾語のつかない8進リテラル又は16進リテラルの場合、その型は、int型、unsignd int型、long int型、unsigned long int型の順に見ていって、その値が表現可能な最初の型とする。

ではこれを踏まえ、VS2005を使って検証してみよう。

int main(int argc, char* argv[])
{
	char sample[] = {
		0x8000000, // int範囲
		0x80000000, // int範囲(2の補数)
		0x800000000, // 標準整数型範囲外
		2147483647, // int範囲
		2147483648, // int範囲外(正数)
		-2147483649, // int範囲外(負数)
		21474836480, // 標準整数型範囲外
		-21474836480, // 標準整数型範囲外
	};

	return 0;
}

VS2005のコンパイラは、型変換によってオーバーフローする可能性のある箇所を見つけると、変換元の型付きでwarningを出してくれる。
なので、これをコンパイルしてwarningを見れば、リテラルの型が分かる。

(4) : warning C4305: '初期化中' : 'int' から 'char' へ切り詰めます。
(4) : warning C4309: '初期化中' : 定数値が切り捨てられました。
(5) : warning C4305: '初期化中' : 'unsigned int' から 'char' へ切り詰めます。
(5) : warning C4309: '初期化中' : 定数値が切り捨てられました。
(6) : warning C4305: '初期化中' : '__int64' から 'char' へ切り詰めます。
(6) : warning C4309: '初期化中' : 定数値が切り捨てられました。
(7) : warning C4305: '初期化中' : 'int' から 'char' へ切り詰めます。
(7) : warning C4309: '初期化中' : 定数値が切り捨てられました。
(8) : warning C4305: '初期化中' : 'unsigned long' から 'char' へ切り詰めます。
(8) : warning C4309: '初期化中' : 定数値が切り捨てられました。
(9) : warning C4146: 符号付きの値を代入する変数は、符号付き型にキャストしなければなりません。
(9) : warning C4305: '初期化中' : 'unsigned long' から 'char' へ切り詰めます。
(9) : warning C4309: '初期化中' : 定数値が切り捨てられました。
(10) : warning C4305: '初期化中' : '__int64' から 'char' へ切り詰めます。
(10) : warning C4309: '初期化中' : 定数値が切り捨てられました。
(11) : warning C4305: '初期化中' : '__int64' から 'char' へ切り詰めます。
(11) : warning C4309: '初期化中' : 定数値が切り捨てられました。

前述の HOGE に相当するのは5行目なので、正解は「unsigned int」。
なぜint型じゃないかと言えば、簡単な話、C++は負数を2の補数で表現することを規定していない(最上位ビット0で負数を表現することも許されている)から。
だから例え2の補数表現で見ればint型の負数であったとしても、符号付きの型にすることはできない。
よって、 HOGE をint型に変換した場合の動作は、符号付き整数型への型変換でオーバーフローが発生するため処理系依存ということになる。

さて、せっかくなので他のパターンも見てみよう。

6行目のリテラルは__int64型(long long型)となっているが、これはC++的には規格外の動作。
gccでも同じように動作するし、『JISX3010:2003』(C99)ではlong long int型になることが規定されているが、少なくとも『JISX3014:2003』はこのパターンに触れていない。

10行目以降も同様、C++的には「未定義」の動作。

だがこの中で特に注意すべきなのは9行目。

(9) : warning C4146: 符号付きの値を代入する変数は、符号付き型にキャストしなければなりません。

検証コードのコメントには「代入されそうな値が負数」だから負数と書いているが、実はここのリテラルは「-2147483649」ではなく「2147483649」。
その前に付いている「-」は符号ではなく(整数リテラルに符号は使えない)、単項マイナス演算子なのである。

これがどういった事態を引き起こすか、もう一つコードを書いて検証してみよう。

#include <stdio.h>

int main(int argc, char* argv[])
{
	long long sample[] = {
		0x8000000000000000LL, // 64bit整数最小数(2の補数)
		-2147483648, // 32bit整数範囲の負数のつもり(0x80000000)
		-4294967295, // 64bit整数範囲の負数のつもり(-0xffffffff)
		-4294967295LL, // 64bit整数範囲の負数(型を明示)
		-4294967296LL, // 64bit整数範囲の負数(-0x100000000)
		9223372036854775808ULL, // 64bit整数範囲外(正数)
		-9223372036854775809LL, // 64bit整数範囲外(負数)
	};

	for(int i = 0; i < 7; i++)
	{
		printf("%lld\n", sample[i]);
	}

	return 0;
}

これはVS2005、g++ 3.2.3、gcc 3.2.3(-std=c99)のいずれでコンパイルした場合も、以下の結果を返す。

-9223372036854775808
2147483648
1
-4294967295
-4294967296
-9223372036854775808
9223372036854775807

見ての通り、代入先が64bit整数型であるにも関わらず、先にunsinged int型で計算されてしまうため、「-4294967295」は「1」となって代入されてしまう。
また特に気をつけなければならないのは、MSDNのC4146の項にも書かれている「-2147483648」。
見た目的には完全にlong int型なのに、64bit整数型に代入すると「2147483648」になってしまう。

ただし、gcc 4.0.1はちょっと違っていて、 g++ でコンパイルした場合は他のコンパイラ同様の結果を返すが、 gcc -std=c99 でコンパイルした場合、2行目と3行目の出力は以下のようになる。

-2147483648
-4294967295

これはC99ではこの2つのリテラルは「unsigned int型」ではなく「long long型」になることが決まっているからであり、C99準拠のコンパイラとしてはこれが正しい動作なのである。

とりあえず再起動 とりあえずログアウト

ここしばらく、Firefoxでニコニコ動画に繋がらなく現象に悩まされていた。

まあ大抵繋がるのだが、一度繋がらなくなるとFirefoxを再起動しないと繋がらない。
再起動しても繋がるとは限らない。

何かの足しにならんかと lsof を繰り返してみたところ、一度ニコニコ動画に繋ぐと

202.248.110.243:http

これがずっと ESTABLISHED になり、繋がらなくなったときにはこれが2つに増えていることが分かった。

Safariで繋いだときにはこの接続はすぐに CLOSED になるから、多分これが原因なのだろう。
色々試してこれを CLOSED に出来れば、問題は解決するはず。
そう思って色々やっていたら、なんと「一度ニコニコ動画からログアウト」するというあまりにも初歩的なことで、以降何度試しても、ちゃんと CLOSED されるようになってしまった。
なんてこった/(^o^)\

考えてみれば、これまでこの不具合を直すために自発的にログアウトしてみたことは一度もない。
普通なら真っ先に試しそうなものだが、他のブラウザでログインするとFirefoxに戻った時に再ログインを要求されるから、それでログアウトした気になっていたのだ。迂闊。

「やった気になってはいけない」

分かっているつもりなのだが、どうしてもどこかで思い込み(ログインを要求される=ログアウトしている)が発生してしまう。
こればっかりは、一人ではどうしようもない――思い込みを指摘できる他者が必要――なんだろうな。

03月03日のココロ日記(BlogPet)

触手ってなんですか?うごめくメモリみたいなものですか?

*このエントリは、ブログペットのココロが書いてます♪

らき☆すた いろいろ

らき☆すたオンライン

アニメイトに行ったら平積みされていたので買ってみた。
著者は前作『らき☆すた殺人事件』同様、竹井10日。

うん、まあ、著者が同じなだけあって、前作同様あまり面白いものではない。
アンソロジーの一片としてならこういうのもあっていいかなぁと思うんだけど、丸々2冊このノリというのはなんとも。
竹井10日の他の著書を先に読んでいれば、まだ楽しめそうではあるが……
しかし作中やたら熱心に自著を宣伝してくるので、何か読んだら負けな気がして仕方ない。

ニコニコ動画

暇な時用にとじりじり見進めていたんだけど、戦争を始めたあたりからの展開がかなり面白かったので、ついつい最新話まで一気に見てしまった。

私は太閤立志伝はプレイしたことがないし、日本史にもとんと疎い。
だから史実と比較してどうこう言うことはできないが、人物や時代の動かし方は相当上手いと思う。
小ネタの織り交ぜ方も上々。
何より大名や武将のキャラ付けが面白く、らき☆すた勢よりむしろそっちに萌える(´ω`*)


久しぶりに過去のMADを見に行ったら、いつの間にか新しい作品が上がっていることに気付く。
今作もネタのレベルは非常に高く、上手い具合に意表を突いてくる。

しかし最近は何故だかこういう「久しぶり」が多いなー。

Safari RSSリーダの不調

タグ: Mac Leopard

最近、といっても1ヶ月以上前からだが、SafariのRSSリーダの調子が悪い。
「アップデートの確認」を「30分ごと」に設定しているのに、OS(というかPubSubAgent)を再起動したり、実際にそのフィードを開くまで更新を通知してくれないことが間々あるのだ。
開かないと更新が判らないって、それではフィードの意味がないだろうと。

Googleで調べてみても、PubSub系の不具合について得られるのは「PubSub:203エラー」の情報ばかりで、この件に関してはさっぱり。
みんな問題なく動いてるのかなぁ……

Appendix

タグ

Blog内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。