Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Jul 29 2015 07:11
    日本語のC++チャットルームです。C++に関連する話題であればなんでも自由に投稿・質問してください。
  • Jul 29 2015 07:10
    日本語のC++チャットルームです。C に関連する話題であればなんでも自由に投稿・質問してください。
  • Jul 29 2015 07:09
    日本語のC チャットルームです。C に関連する話題であればなんでも自由に投稿・質問してください。
  • Jul 29 2015 07:07
    てすと from nyaocat
nyaocat
@nyaocat

あと疑問の趣旨と全然関係ないですが, void は不完全型なので default_deleter のまま unique_ptr<void> 使うと dtor で怒られるっていう話があってですね.

そういえば確かに…… せめてint とかにしておけば良かったですね。まぁ趣旨とは関係ないとこなんですが

Cryolite
@Cryolite
あ,すんまそん.普通に見落としてましたん.>使えたとしても
Kohei Takahashi
@Flast
そうだ、std::tuple<T...>::tuple(std::tuple<U...>&&)はexplicitなので、結局std::make_tupleを使わざるを得なくて、とても長くなるので、なんとかならないかなって思ってたんだった
return {std::move(x), std::move(y)}; // error
return std::make_tuple(std::move(x), std::move(y)); // ok
ままならぬ...
nyaocat
@nyaocat
あ、explicitだったか……。make_tupleにmoveも書かねばならないとなると、やろうとしてる事に対してコードが長くてなんか嫌ですねこれ
Kohei Takahashi
@Flast
おっとみす std::tuple<T...>::tuple(std::tuple<U...>&&)これじゃなくて std::tuple<T...>::tuple(U...&&)こっちがexplicit
arithmeticae
@marionette-of-u
はじめまして。C++03以降がLR(1)クラス構文って本当ですか。オペレーターオーバーロードがあるからっていう理由を聞いたのですがいまいち納得できません。
nyaocat
@nyaocat

構文解析については詳しくないので、 https://ja.wikipedia.org/wiki/LR%E6%B3%95 を読んだのですが、この記事中に

多くのプログラミング言語がLR法(およびそれを一部改変したもの)で構文解析できる。例外として、C++とPerlがある。

との記述がありますね。

Wikipediaには理由は書いてませんが、うろ覚え知識だと、 A * B ; とあった際にこの文だけではABの乗算なのかA*型の変数Bの宣言なのか区別が付けられないので、一般的な構文解析が出来ない、とどこかで読んだ気がします。
オペレーターオーバーロードが関係するかは……僕の知識不足で分かりません。
nyaocat
@nyaocat

オペレーターオーバーロードがあるから

という記述の出典元を示して下さると、他の方が答えやすくなるかもしれません。

Kohei Takahashi
@Flast
適当にぐぐったらこんなエントリが見つかりました
http://d.hatena.ne.jp/kazu-yamamoto/20081201/1228115457
arithmeticae
@marionette-of-u
オペレーターオーバーロードが理由という話は昔StackOverflowで見かけました。
nyaocat
@nyaocat
stackoverflowに C++ が LR で解析できないことについてそのものズバリな質問がありました。 Why can't C++ be parsed with a LR(1) parser?
C++は オペレーターオーバーロードに関係なく LR(1)クラス構文ではないようですね。
arithmeticae
@marionette-of-u
なるほど。ありがとうございます
Kohei Takahashi
@Flast
人増えてきた!
nyaocat
@nyaocat
めでたい(?)
Cryolite
@Cryolite

初心者質問ですいません!

int main() {
  int *p = nullptr;
  *p = 42;
}

が undefined behavior を起こすかどうかを純粋に規格の文言だけから結論できますでしょうか?

Kohei Takahashi
@Flast

微妙にそれるけど明らかなものとしては、pointer to member typeに関してはn4296 [expr.mptr.oper]/6に

If the second operand is the null pointer to member value (4.11), the behavior is undefined.

ってあるので、これはUB

で、本題の方はちょっと怪しくて、

揚げ足を取るような読み方すると、まずn4296 [dcl.ref]/5に

A reference shall be initialized to refer to a valid object or function. [ Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by indirection through a null pointer, which causes undefined behavior.

というのがあって、じゃぁreferって何ってなるとn4296 [expr.unary.op]/1には

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points.

とあるので、nullptrの位置にvalid objectがないことを示せればなんとかUBに持ち込めそう

Kohei Takahashi
@Flast
n4296 [dcl.ref]/5にUBって書いてあるじゃんって指摘には、これはNoteなので規格の挙動に影響を与えられないっていうのがあって書いてあるのに残念
op->*op[]に関してはそれぞれop.*op*へのequivalenceであることが示されているので割愛
Kohei Takahashi
@Flast
.oO(*がmarkdownに食われるの何とかできないかな...
nyaocat
@nyaocat
規格書さらってみましたけど Flast さんが既に書いてる以上の関係ありそうな文言はみつけられず _(:3 」∠)_
*アスタリスクは 先に \ をいれてやればエスケープできるみたいですね。 *
This message was deleted
Kohei Takahashi
@Flast
恐らく、*nullptrはUBですよってなると、組み込みとかでfree standing env.してる時に、ほんとにHWのアドレス0にアクセスする必要があった時に規格違反のコンパイラを作らないといけなくなってしまうから、あくまでvalid objectという表現に抑えてあるのではと推測
nyaocat
@nyaocat
あれ、 null pointer が アドレス 0 だとは規定されてないのでは?アドレス 0 にアクセスしうるような環境ならば別の値を null ポインタとすればよいはず
Kohei Takahashi
@Flast

お、確かに、n4296 [conv.ptr]/1だと

A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t.
A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type
and is distinguishable from every other value of object pointer or function pointer type.

と書いてあるだけで確かにnull pointer valueが0であるとは規定していないな

じゃぁ陽にUBにしていない理由が別にあるのかな...
nyaocat
@nyaocat
void f(int*);
std::vector<int> vec;
f( &vec[0] );
で vec が empty の時に実装によっては null のデリファレンスを起こして UB になるのを防ぐためとか……?
C++11以降なら vector<T>::data() を使えばよいですけど、 C++03 だと data() がなくて &vec[0] とか &(*vec.begin()) とか書いてるコードも多かったでしょうし。
ignisan
@ignisan
この辺読んでたけど初心者だから難しかった http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232
Cryolite
@Cryolite

おぉ! CWG issue 232 は見落としていました! ありがとうございます! 現在の方向性は, indirection は許容して lvalue-to-rvalue conversion の段階で U.B. にしよう,ということですか.だとすると,関連する疑問であった

class X {
  void f();
};

int main() {
  X *p = nullptr;
  p->f();
}

は X::f で this が指している empty lvalue に対して lvalue-to-rvalue conversion が走らない限り完全に規格に準拠した well-defined program (ということに将来的にはなりそう)ということですか.

Kazutoshi SATODA
@k-satoda

未定義動作の話と聞いて混ざりにきました。

@Cryolite 現状の規格では * 演算子の結果が有効なポインタについてしか規定されていないので、現状は未定義動作という結論になるかと思います。(ヌルポインタniの場合の動作について処理系に対してなんの制約も無い)

明記が無いことも含めて規格の不備であるのは CWG #232 のとおり間違いないと思います。

this != nullptr を前提とした最適化がすでにいくつかのコンパイラで行われているので、非 static なメンバ関数呼び出しはメンバアクセスと同様に未定義のままとなるべきだろうと思ってます。ここらへん、修正案では抜けてる感じ。

2005 年の Note を最後に CWG #232 の進展が無いのはおかしいだろうと思うので std-discussion に投げて話を進めたほうがいいと思うんですけど、そんなつもりは無いですか?(このチャットルームで規格文面の話をするのもどうかと思うので・・・。)

Kohei Takahashi
@Flast
ちょっと気になったので質問です http://melpon.org/wandbox/permlink/tXlwc27Gi0ZPfNFN
これってwell-defined or UBどっちかわかる方いますか?
(単純にPDF開くのだるいとも言う
arithmeticae
@marionette-of-u
こんにちは
Type Erasureってむつかしいですね。
https://gist.github.com/marionette-of-u/7daa71220358746dc634
void pointerからbase-derivedの型消去に書き直したいけどエンバグしそうで怖い
Kohei Takahashi
@Flast
@marionette-of-u taskmainに型が現れてしまっているのでTypeErasureで書き直したいということですか?
arithmeticae
@marionette-of-u
はい。それもあります。現状ではtemplate関数を噛ませることで前方宣言を回避してラップしてますが、利便性に欠けます。
あとここのクラスにあるワーキングエリアがvoid*なので、できれば継承関係を使うTypeErasureの方がC++としてベターかなと。
https://gist.github.com/marionette-of-u/7daa71220358746dc634#file-tasklist-hpp-L50
arithmeticae
@marionette-of-u
∀any_type, std::is_same<void_type, any_type>::value == false (∧ std::is_same<void_type, void_type>::value == false) となる予約語void_typeがほしい
iya,
使いどころがない!
Kohei Takahashi
@Flast
まずはじめにTypeErasure以前に、型が現れてる状態でstorage作ったりして自前でどうこうする必要はなくて、std::tupleとかにまずはtask列を投げ込めばalloc/deallocとかややこしいことしなくていいのではというのがあります
arithmeticae
@marionette-of-u
いや、Types and Programming Languagesに応用方法と導入の難易度がすべての基底クラスの導入難易度と比較されていたような
実はC++03の時代にboostとvirtual tableが嫌いで書いたものをC++>=11に移植したものです