C++相談室 part162

■ このスレッドは過去ログ倉庫に格納されています
1sage (ワッチョイ fbf0-ofdD)
垢版 |
2022/10/31(月) 14:29:35.57ID:J5sgTSch0
!extend:checked:vvvvv:1000:512
!extend:checked:vvvvv:1000:512
↑同じ内容を3行貼り付けること

次スレは>>980が立てること
無理なら細かく安価指定

※前スレ
C++相談室 part161
https://mevius.5ch.net/test/read.cgi/tech/1653135809/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
2022/11/11(金) 00:26:17.38ID:NMTpQElqM
>>62
[補足]
JSなどの動的で初心者ならば、「大体」で理解していればそれで問題無い事が
多いだろうが、C++では、テンプレートもあればoperator+()演算子や型変換
演算子などをオーバーロードできるから、「大体」では駄目で、非常に細かな
コンパイルの順序や解釈の流れまでが言語の仕様書に厳密に書いてなければ
正しいアプリケーションコードを書くことが出来ないことがある。
「直感的に簡単に理解できるのに、何この馬鹿は聞いているんだ?」
などと思っているとすれば、大間違いだ。
2022/11/11(金) 00:28:53.35ID:L/uUC/Rw0
質問はしたのだから、回答を待っていればいいだろうに
何でまた独り言を延々と書いてるのか、不思議だ
書くなら自分の日記帳に書けばいいのでは
2022/11/11(金) 00:32:42.01ID:NMTpQElqM
>>63
[補足]
>>28で、phone_bookの初期化子について、「直感的に」理解できたら
それで十分、などと考えている人は、馬鹿なので質問には答えないで下さい。
C++コンパイラは、そのように大体で動作しているのではなく、パターン
に当てはめて順序を追ってコンパイルを進めていきますが、その順序や
解釈の仕方がC++03の時代とはかなり違っているように思えたから
質問したのです。
例えば、>>28は単なる例であって、これの応用として非常に複雑なコードを
書いた場合でも、コンパイラはなんたかの単純な法則に従って厳密に翻訳していきます。
その正確な規則が分からないから聞いているのです。
2022/11/11(金) 00:33:22.29ID:NMTpQElqM
>>64
馬鹿な人が茶々入れしてきたので、排除する努力をしています。
2022/11/11(金) 00:40:51.17ID:NMTpQElqM
>>59
>Entryのようにstringとintを持った構造体なら集成体初期化になるし、
今回の例では、vector<Entry>型の初期化ですので、そんな単純ではありません。
vector<T,A>テンプレートのコンストラクタが呼び出されるはずです。
しかも、コンストラクタの種類が沢山ありますから、それを選ばなくてはなりません。
Entry a = {"xxx",1234};
ならば集成体初期化ですから、コンストラクタを選ぶ工程は無いはずですから、
比較的単純です。
ところが、今回の場合は、コンストラクタの選択から始まります。
しかし、初期化子自体の型が中途半端な状態でコンストラクタを選ぶ必要が
ありそうなので質問しているのです。

C++03で、x+y書いた場合、xとyの型が決まった後で、operator+(U,T)演算子を探します。
ところが今回の場合、初期化子の部分の型が中途半端な状態なので、コンストラクタを探す
ための手がかりが中途半端にしかないのです。
2022/11/11(金) 00:45:48.11ID:NMTpQElqM
>>67
[補足]
CPerson person{"Suzuki", 25};
と書いた場合、CPersonのコンストラクタはすぐ探せます。
ところが、>>28 のように
vector<Entry> phone_book = {
 {"David Hyme",123456},
 {"Karl Popper",234567},
 {"Bertrand Arthur William Russell",2345678}
};
の場合、テンプレート vector<T,A> の中のコンストラクタを選ぼうとしても、
初期化子の{"David Hyme",123456}には、ある意味では「型が存在してない」ので
通常のように探すことは出来ないのです。
2022/11/11(金) 00:48:44.75ID:J8vKnsQy0
>>65
正確な規則が知りたいのに規格に当たることすら思いつかないのか自称天才のボンクラ様ってのは
9.4 Initializers [dcl.init](C++20公開ドラフトN4861、正規の規格がいいなら自分で買え)を見ればいいよ
誰でも読めば分かるように書いてある規格を天才様が理解できないなんてありえないから以降質問禁止な
2022/11/11(金) 00:55:21.61ID:NMTpQElqM
>>68
[補足]
vectorは配列と似ていますが、コンパイラの内部的にはかなり違う扱いになっていて、
Entry a[3] = {
 {"David Hyme",123456},
 {"Karl Popper",234567},
 {"Bertrand Arthur William Russell",2345678}
};
と書いたならば、コンパイルの翻訳過程は全く異なってきます。
この場合はとても単純で、
T a[N] = {XXX};
の形式は、配列初期化として特別処理されています。
なので、コンストラクタを探す工程、というものが必要ありません。
そして、{"David Hyme",123456} の型を知る必要も無く、単純に、
Entryのメンバに代入していくような処理となります。
この場合の処理は、まず最初に配列型として処理が入り、次にEntryの構造体型
としての処理が入ります。
これが理解できない人は質問には答えないで下さい。混乱の元になります。
2022/11/11(金) 00:56:13.87ID:NMTpQElqM
>>69
そんな言い方されれば質問サイトの意味が無いわけです。
2022/11/11(金) 00:59:02.50ID:J8vKnsQy0
>>68
あまりにも馬鹿すぎて哀れだからもう1回だけ助け舟出してやる
いいか?vector<Entry>がどんなコンストラクタ持ってるか(どうオーバーロードされてるか)は決まってんだよ
vectorテンプレートを実体化した時点で静的に全部決まってんだよ
馬鹿なお前だって<vector>ヘッダを隅々まで読めば列挙くらい出来るのは分かるだろ
vector<Entry>のコンストラクタは例えばvector<Entry>()とかvector<Entry>(size_type)とかvector<Entry>(vector<Entry>&&)とかvector<Entry>(initilaizer_list<Entry>)とか色々あるわけだな(全部は挙げんぞ)
コンパイラ様はまずそれを列挙するわけだ。そして
・vector<Entry>()かな?→空じゃないからダメ
・vector<Entry>(size_type)かな?→{...}はsize_typeに変換できるかな?→ダメ
・vector<Entry>(vector<Entry>&&)かな?→{...}はvector<Entry>&&に変換できるかな?→ダメ
・vector<Entry>(initilaizer_list<Entry>)かな?→{...}はinitilaizer_list<Entry>に変換できるかな?→OK!
・...
ってひたすら一つずつ試すわけだ。で、vector<Entry>(initilaizer_list<Entry>)しか当てはまるものがないので、じゃあこれだとオーバーロードを解決するわけだ
コンパイラのやってることなんて基本的にこれだけだ、実に単純な話だ
こんな単純なこともわからずグチグチグチグチとお前は本当に無能だな
2022/11/11(金) 01:02:30.49ID:NMTpQElqM
>>72
その探し方は、普通の関数のオーバーロード解決とは異なっていますね。
しかも、あなたの言っているほど単純じゃない。
実際は、優先順位があり、先に優先順位の低いものが見つかって、後から
優先順位が高いものが見つかっても、後の方が優先される。

あなたが馬鹿なのは、単純に考えすぎていることだ。
2022/11/11(金) 01:03:31.20ID:J8vKnsQy0
>>71
なんで答えが書かれた文書が誰でも読めるように公開されてるのに、わざわざ自分より劣った人間に答えを求めるの?
お前天才なんだろ?ここの誰よりも賢いんだろ?
消えな
2022/11/11(金) 01:04:06.86ID:hvQf6BDd0
>>74
すまんがお前が消えてほしい
相手するからつけあがる
2022/11/11(金) 01:05:05.21ID:NMTpQElqM
>>73
[補足]
なお、関数のオーバーロード解決でも、「変換できるかどうか」とかそんな単純な
ものじゃないです。
例えば、T a{x} のように{}が書いてあれば、中味が1個しか書いてなくても、
initializer_list が優先される、などと決まってます。
2022/11/11(金) 01:05:24.11ID:J8vKnsQy0
>>73
だから正確なのが知りたいなら規格読めやボケカス
お前のゴミ虫みたいな脳みそに合わせてわざわざ単純化してやったのに何だその物言いは無礼者の恥知らずが
2022/11/11(金) 01:06:38.58ID:NMTpQElqM
>>74
俺よりC++を知っている人だってこの世にいるから質問してる。
それでは質問サイトの意味がない。
調べればわかることでも知ってる人に聞いたほうが早い。
2022/11/11(金) 01:07:31.06ID:J8vKnsQy0
>>76
T a{x}ってそれ関数じゃなくて変数定義ですよ
そんな区別もつかないレベルじゃ規格書なんて早かったかなごめんね
でもそれも規格書に書いてあるから読んで勉強しろ
2022/11/11(金) 01:07:50.72ID:NMTpQElqM
>>77
あなたみたいなのが日本を衰退させている。
自分が頭がいいと思い込んでいるがかなり間違ってるし、レベルが低い。
そして、あなたの周りにはレベルの低い人しか回りに居ないから勘違いが
直らない。
2022/11/11(金) 01:08:28.22ID:NMTpQElqM
>>79
アホですか。
コンストラクタを探す話をしている。
2022/11/11(金) 01:09:07.49ID:J8vKnsQy0
>>78
ここで俺や他の人が説明してあげてる内容すら理解できないなら、規格書を泣きながら読むか死んだほうが早いと思うよ
2022/11/11(金) 01:10:04.92ID:NMTpQElqM
日本は分断化が激しい社会だ。
カシコが一部に集まり、アホがあほ同士集まっている。
だから自覚できない。
そういう社会にしてしまっていることが問題。
2022/11/11(金) 01:10:52.44ID:J8vKnsQy0
>>81
1行目のせいで関数のオーバーロード解決の話をしてるもんだと思ったよ
どうやらC++以前に日本語すら不自由なようだね
2022/11/11(金) 01:11:25.32ID:NMTpQElqM
>>82
お前は理解できてないのに質問に答えようとしている。
いつもは質問のレベルが低いから答えられているんだろうが、今回は
お前の能力を超えている。
そしていつもの調子で質問者をレベルが低いと思い込んでいるから
馬鹿にした態度をとる。
2022/11/11(金) 01:11:57.99ID:NMTpQElqM
>>84
お前に言われたくない。
2022/11/11(金) 01:14:33.80ID:NMTpQElqM
>>82
「してあげている」
って、おまえの思ってる直感的理解と、俺の求めている理解とは次元が違う。
お前は、いっぱんぴーぽーとしてC++を使えてもそれ以上はできないだろう。
2022/11/11(金) 01:16:18.16ID:J8vKnsQy0
もう終わりにするけど、俺の説明が間違ってるって言うならそれは規格と主要コンパイラの実装が間違ってるってことだから
ISOとベンダーに報告しときなよ

>>75
ごめんなさいみなさん久しぶりに面白いおもちゃだったのでつい
2022/11/11(金) 02:19:52.16ID:tp0srwYgd
キャラ剥がれてきてて草
2022/11/11(金) 05:29:55.03ID:wl59B58M0
std::array<T, N>って「N個の値xで埋める」コンストラクタありませんよね?
後でstd::fillするのが普通のやり方かもしれませんが、実際はstd::arrayのインスタンスができた時点でN個の何らかの初期値が入るんですよね?
この仕様に困ってます。
例えば、boost::multi_arrayは構築時にメモリの並び方 (Cライク or fortranライク) が決まって、後で変更する方法は提供されてないんですが、 std::array<boost::multiarray, N> を作ってしまうとメモリの並び方が勝手に決まってしまいます。
std::array の各要素のコンストラクタをこちらで呼ぶ方法があったら教えてください。
初期化リストで構築するやり方はNが大きいときは現実的でないので考えておりません。
2022/11/11(金) 07:32:36.01ID:fbtAWiSRH
>>54
逆はないと思いますよ
2022/11/11(金) 07:44:40.78ID:J8vKnsQy0
>>90
残念ながらarrayで初期化時にやるのは無理
arrayは組み込み配列と同じ初期化方法(集成体初期化)しか出来ないように意図的に設計されてて特別なコンストラクタを持たない
だからarray::fill()が用意されてるので普通はそれを使う
どうしてもその場で要素のコンストラクタを直接呼びたいなら一回構築してから要素ごとにデストラクタ→placement newを呼ぶしかない
最初のデフォルト構築も許せないならarray(と組み込み配列)を使うのは諦めよう
2022/11/11(金) 15:28:43.83ID:x9X8FiGQM
>>91
いくらアインシュタインが相対性理論を説明しても、一般人には理解できない。
どんなに天才でも、説明できない事柄がある。
2022/11/11(金) 19:19:22.94ID:+I+8FBiLd
天才ほど説明が下手だね
天賦の才に頼らず這い上がった苦労人タイプの
説明のほうが一般人には分かりやすい
2022/11/11(金) 20:11:09.74ID:MfyOP1HR0
わかった気になるだけってやつね
完全に理解する必要のない一般人ならそれもあり
2022/11/11(金) 20:47:56.26ID:76yLxZ0B0
誰かを見下していなきゃ自分を保てない小さいやつ
2022/11/11(金) 23:42:57.00ID:jawQM+EmM
確かに右辺値参照あたりの仕組みはコピー減らそうという意図が感じられる割に徹底しようとするとstd::arrayとかのctorで足元すくわれがち
2022/11/12(土) 01:01:47.32ID:0JLM8m+J0
ワッチョイつけると炎上しなくて良いね
2022/11/12(土) 07:48:03.70ID:GOjTxZ8j0
arrayは組み込み配列の糞さ緩和が目的なので糞が多少まろび出るのは仕方ないんよね
2022/11/12(土) 09:59:28.06ID:D5o/xiXJ0
>>92
collectionで初期化も無理なんだ?
せめてvectorで初期化できるなら良かったのにね
2022/11/12(土) 11:30:02.52ID:GOjTxZ8j0
1つでもコンストラクタを独自定義したら集成体になれないので仕方ない
2022/11/12(土) 14:25:39.92ID:5guAadWy0
>>90
要素のデフォルトコンストラクタは呼ばれるので要素のほうに適当なラッパーを被せるという方法はとれなくはない。
こういうラッパーならスタンダードレイアウトの要件は満たすのでバイト列レベルでも互換性は維持されるはず。

#include <array>
#include <iostream>

struct foo {
// このコンストラクタを呼んで欲しい
foo(int x){
std::cout << x << std::endl;
}
};

template <class T, auto N>
struct initializing_wrapper : public T {
initializing_wrapper(void) : T(N) {}
};

int main() {
std::array<initializing_wrapper<foo, 1> , 3> foo;
}
2022/11/12(土) 23:48:04.66ID:2iksiTkL0
vscodeでeigen使ったコード書いてるんだけど、デバッグ時にeigenの変数見る方法ある?
visualstudioならあるっぽいんだけど、vscode上でしょりしたいんだよね
2022/11/13(日) 00:14:31.39ID:5VmZbZRR0
普通に変数ウォッチで見えんの?
2022/11/13(日) 04:06:31.61ID:L3LR+iGt0
ちょ、何これ? 聞いてないんだけど。。。

C:/msys64/mingw64/include/c++/12.2.0/bits/stl_pair.h:326:13: note: declared here
326 | pair& operator=(const pair&) = delete;

C:/msys64/mingw64/include/c++/12.2.0/bits/stl_pair.h:715:5: note: declared here
715 | swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
2022/11/13(日) 07:39:53.36ID:alAGhxI40
>>103
eigen一回も使ったことないしググってもないけど、行列の先頭要素のメモリにアクセスする方法が提供されてないわけないので、それを使う
普通はdata()とかget()なるメンバ関数がある
2022/11/13(日) 11:52:46.36ID:7rETCoZw0
>>105
-std= で規格を指定するとか?
2022/11/13(日) 12:42:20.71ID:JmrIg+tw0
-std=c++20にしてる
2022/11/13(日) 14:31:41.33ID:sejtbDAm0
>>105
本来使われるはずの定義はこっち。
https://github.com/gcc-mirror/gcc/blob/e24b430f1ea60205162fd9b327ac6a4dfc57f37c/libstdc%2B%2B-v3/include/bits/stl_pair.h#L371-L379

必要な性質 (要素の型が copy_assignable) が満たされていないときに最も優先度が低いやつが選択された上でそれが delete されているということになるんだと思う。
https://github.com/gcc-mirror/gcc/blob/e24b430f1ea60205162fd9b327ac6a4dfc57f37c/libstdc%2B%2B-v3/include/bits/stl_pair.h#L368
2022/11/13(日) 16:56:29.94ID:L3LR+iGt0
壮大なSFINAEってわけか・・・
元コードは晒せないんであとは自分で探すしかないな

ヒントありがと、餃子さん
2022/11/13(日) 18:18:04.90ID:sejtbDAm0
どうせ使えないなら使おうとしたときに static_assert で問題点を出すようにしたらいいのにと思ったがよく考えるとそれは駄目なんだな。
適用できるものがないということを SFINAE のトリックに使うことがあるかもしれない。
(static_assert が展開されると他の候補があっても問答無用で終わりになってしまう。)
2022/11/13(日) 18:23:28.51ID:BN7kyEsvM
いつもサナエさんにはお世話になってる
113デフォルトの名無しさん (アウアウウー Saa9-FFna)
垢版 |
2022/11/14(月) 12:10:20.06ID:EWF0SvAna
>>94-95
天才とパンピーで理解レベルのバックグラウンド知識に差があるからだろ
その差を埋める説明を一瞬で出来る人はそれなりの才能があるとは思うが
天才同士ならそんな説明いちいちしなくても判り合えるんだ
2022/11/14(月) 19:05:49.95ID:KWfGC8qSd
天才はそもそも他人の説明なんかいらんからな
2022/11/14(月) 22:27:38.95ID:sRgsAS70H
自分が天才だ!とわざわざ自称しなくても、天才らしい雰囲気をかもし出せるレスはないものでしょうかね…
自称天才はもういいし
2022/11/14(月) 22:42:37.02ID:rM2EwItV0
ギフテッドって凄すぎて訳わからんからな
2022/11/15(火) 12:36:06.45ID:+zOZoQ9YM
プログラミング言語 C++ [第四版], 日本語訳 の p.689 に、
template<typename T>
class Xref {
 ・・・
};
template<typename TT, typename A>
unique_ptr<TT> make_unique(int i, A&& a)
{
 return unique_ptr<TT>{new TT{i,forward<A>(a)}};
}
auto p1 = make_unique<Xref<String>>(7,"Here");
「ここで、"Here"は右辺値なので、右辺値を引数にしてforward(string&&)
が呼び出される。」
とありますが、実引数の文字列リテラル "Here" が、make_unique()の
仮引数 A&& に渡そうとしたら、A = string と「演繹」されているようですが、
const char* 型が string に至るまでの仕組みか分かりません。
どなたが分かる人居ませんか?

実際の STL の sting は basic_string<U> テンプレートの U=charの
場合だと思われますが、意味を概念的に言えば、
class string {
public
// 変換コンストラクタ :
string(const char *) {・・・}
};
という「変換コンストラクタ」があるでしょうから、それが使われている
ことは推定は出来ます。
しかし、上記のテンプレートで T を演繹する際に、このような変換コンストラクタ
が呼び出されるメカニズムが分かりません(仕様書のどこに書いてあるのかが
分からない。)。
2022/11/15(火) 12:51:05.19ID:+zOZoQ9YM
>>117
もっと詳しく書くと、直前から次のように書かれています:
# Xref<String>はXref<string>の写し間違いでした。
string x {"There and back again"};
template <typename T>
T&& std::forward(typename remove_reference<T>::type& t) noexcept;
template <typename T>
T&& std::forward(typename remove_reference<T>::type&& t) noexcept;
ここで望まれるのは、不純なコピーを一切作ることなく、
make_unique<T>(arg)がargからTを構築することである。
その実現には左辺値と右辺値の区別を管理することが重要だ。
次の例を考えてみよう:
template<typename TT, typename A>
unique_ptr<TT> make_unique(int i, A&& a) // make_sharedのちょっとした変種
{
 return unique_ptr<TT>{new TT{i,forward<A>(a)}};
}
auto p1 = make_unique<Xref<string>>(7,"Here");
ここで、"Here"は右辺値なので、右辺値を引数にしてforward(string&&)
が呼び出される。
そして、"Here"を格納しているstringのムーブを行なうために、
Xref(int,string&&)が呼び出されることになる。
# 個人の感想: これは、A=stringと考えられます。
もっと興味深い(しかも分かりにくい)のが、次のものだ:
auto p2 = make_unique<Xref<string>>(9,x);
ここで、xが左辺値なので、左辺値を引数にforward(string&)が呼び出される。
forward()のTは、string& と導出される。そのため、返却値は string & &&となる。
もちろんそれは string & を意味する(§7.7.3)。その結果、左辺のxに対して、
Xref(int,string&)が呼び出されて、xがコピーされる。
# 個人の感想: これは、A=string&と考えられます。
2022/11/15(火) 12:53:27.82ID:+zOZoQ9YM
>>118
[参考]
p.724,
「文字列リテラルは、テンプレート引数には『渡せない』」
ただし、これがどう関係しているのかは不明です。
A&& a の部分に文字列リテラル"Here"を渡してはいますが。
2022/11/15(火) 12:56:01.43ID:f326q+3ca
ある型が来たらそれに応じた変換をするのが、何か問題なんでしょうか
2022/11/15(火) 12:57:17.27ID:slZuGS0Ed
make_uniqueの実体化の所でTT=Xref<String>、T=Stringって明示的に指定してるじゃん
「演繹」なんかするまでもないから規格に書いてるはずもない
天才のくせにそんな事も分からないの?
2022/11/15(火) 13:00:23.02ID:+zOZoQ9YM
>>119
[ヒント]
前頁p.688の下段:
「左辺値と右辺値は、テンプレート引数の導出では区別される。
X型の左辺値はX&として導出されて、右辺値はXとして導出される。
これは、非テンプレート引数の右辺値参照への値のバインド
(§12.2.1)とは異なる。
しかし、引数転送(§35.5.1)においては、極めて有用だ。
Xrefを空き領域上に置いて、そのポインタをunique_ptrとして
返すファクトリ関数を記述する場合を考えてみよう:

の直後、ページが変わってページの最初に>>118の std::forward テンプレート
の定義が書いて有ります。
2022/11/15(火) 13:02:34.01ID:slZuGS0Ed
引用の範囲超えてるんで著作権侵害の疑いで削除依頼出しますね
2022/11/15(火) 13:03:00.86ID:+zOZoQ9YM
>>121
TTは、Xref<string>と明示的に指定されてますが、AはTTとの関係は
書いて無いはずです。
なので、それだけでは、A=stringとは分からないはずでは。
2022/11/15(火) 14:16:43.16ID:D78/LkiC0
new TT{i, forward<A>(a)}
既出だが、こう書いてあってもXrefのメンバの型がどうなるか分からんわけでしょ

先日の質問と合わせて、型パズルをスラスラ解けるような資質がない
資質がないんでXrefの『関係ない』としたところを「・・・」で埋めてる
2022/11/15(火) 15:01:57.79ID:5Bng48RE0
>>117
どういう文脈で説明されてるのかよくわからんが
引数が文字列リテラルの "Here" なら A は const char (&)[5] に推論されるよ。
2022/11/15(火) 16:18:06.60ID:Q+AZCxhHM
>>126
命題『A が const char (&)[5] に推論される』・・・☆
とし、背理法で考えます。
☆が正しいと仮定すると、
forward<A>(a)は、forward<const char (&)[5]>(a)となりますが、すると、
template <typename T>
T&& std::forward(typename remove_reference<T>::type& t) noexcept;
template <typename T>
T&& std::forward(typename remove_reference<T>::type&& t) noexcept;
に対して、forward<const char (&)[5]>(a)
が呼び出されることになります。
しかし、
>auto p1 = make_unique<Xref<string>>(7,"Here");
>ここで、"Here"は右辺値なので、右辺値を引数にしてforward(string&&)
>が呼び出される。
とBJ stroustrup氏が書いています。
ならば、T=const char (&)[5]の時に、
typename remove_reference<T>::type
がstringにならなければなりません。つまり、
typename remove_reference<const char (&)[5]>::type
がstringになってないと矛盾する事になります。
もし、矛盾するならば、背理法により、☆は否定されることになります。
(矛盾しそうです。)
2022/11/15(火) 16:42:50.09ID:Q+AZCxhHM
>>127
これは背理法とは言わなかったわ。
スマソ
2022/11/15(火) 16:49:22.19ID:f326q+3ca
メロスはポリモーフィズムがわからない
2022/11/15(火) 17:18:50.72ID:eijjsxUX0
Perfumeの楽曲だろ?
2022/11/15(火) 18:04:53.44ID:5Bng48RE0
>>127
> ここで、"Here"は右辺値なので、右辺値を引数にしてforward(string&&)
> が呼び出される。

文字列リテラルは左辺値。 右辺値だと書いてあるのならそれが間違っている。
配列がポインタに (暗黙的でも明示的でも) キャストされる文脈では
そのポインタは xvalue (おおよそ右辺値のような扱いになる分類) になるが、
今回は変換が入らずに参照で受けているのでそうはならない。

/// この場合は rvalue 扱い
#include <cstdio>
void foo(const char *&x) { std::printf("lvalue"); }
void foo(const char *&&x) { std::printf("rvalue"); }
int main(void) { foo("abc"); }

/// この場合は lvalue 扱い
#include <cstdio>
template <class T> void foo(const T &x) { std::printf("lvalue"); }
template <class T> void foo(const T &&x) { std::printf("rvalue"); }
int main(void) { foo("abc"); }
132デフォルトの名無しさん (ワッチョイ d55f-cfOC)
垢版 |
2022/11/15(火) 18:53:35.18ID:mUSyU2rD0
文字列リテラルが左辺値ってなんで?
2022/11/15(火) 20:56:02.85ID:aOXxipO5M
文字列リテラルは実際は配列
⇒アドレスで区別できるメモリ上のオブジェクト
⇒つまりlvalue
2022/11/15(火) 20:56:58.78ID:kbPjYi7D0
文字列リテラルはメモリ上に永続的に保持されるんだから勝手に持ってっちゃダメでしょ
2022/11/15(火) 21:11:40.64ID:DJ4SZBHq0
文字列リテラルは配列型のlvalue
文字列リテラルが左辺値変形されて生じたポインタはrvalue
2022/11/15(火) 23:54:26.84ID:5Bng48RE0
配列 (文字列を含む) と関数は値として扱えない、勝手にポインタに型変換するという
C から引き継いだ変則的なルールに辻褄を合わせているので全体的に変則的で
分かりにくいんだよ……。
2022/11/16(水) 00:19:44.88ID:g3O9ReAZM
>>131
>auto p1 = make_unique<Xref<string>>(7,"Here");
>ここで、"Here"は右辺値なので、右辺値を引数にしてforward(string&&)
>が呼び出される。
と書かれています。
なので、"Here"がなんらかのメカニズムでstd::stringに変換されていると
解釈しました。
実験すれば白黒はっきりさせることが出来るかも知れません。
2022/11/16(水) 00:20:20.66ID:DtzZSdSg0
マジで間違った方向に引きずり回してんのか
やっぱりすげーな
こいつは上級者だ
2022/11/16(水) 00:29:08.01ID:g3O9ReAZM
>>138
C++の父であるところのBJ Stroustrup氏が直々に書いていることなのですが。
2022/11/16(水) 00:32:07.57ID:Nbbm6FAB0
禿本手元にないから確認はできないけど、「"Here"が右辺値」なんて基本的な間違い書くとは思えないんだけど
侵害くんの読み間違いか書き間違いか、本当に書いてあるなら翻訳ミスじゃないの
2022/11/16(水) 00:32:57.76ID:Nbbm6FAB0
>>139
"Here"の配列→(配列とポインタの糞ルール)→const char*→(stringの変換コンストラクタ)→string
と変換された結果のstring一時オブジェクトが右辺値だってクドクド書いてない?ちゃんと読んだ?
2022/11/16(水) 00:38:01.28ID:g3O9ReAZM
原書(英語版)はこうなってます:
23.5.2.1. Reference Deduction
...

template<typename T>
class Xref {
public:
   Xref(int i, T* p)    // store a pointer: Xref is the owner
      :index{i}, elem{p}, owner{true}
   {}
Xref(int i, T& r)    // store a pointer to r, owned by someone else
      :index{i}, elem{&r}, owner{false}
   {}
Xref(int i, T&& r)   // move r into Xref, Xref is the owner
      :index{i}, elem{new T{move(r)}}, owner{true}
   {}
~Xref()
   {
      if(owned) delete elem;
   }
   //...
private:
   int index;
   T* elem;
   bool owned;
};
...
2022/11/16(水) 00:38:41.12ID:g3O9ReAZM
>>142
template<typename T>
  T&& std::forward(typename remove_reference<T>::type& t) noexcept; //§35.5.1
template<typename T>
  T&& std::forward(typename remove_reference<T>::type&& t) noexcept;
template<typename TT, typename A>
unique_ptr<TT> make_unique(int i, A&& a)   // simple variant of make_shared (§34.3.2)
{
  return unique_ptr<TT>{new TT{i,forward<A>(a)}};
}

We want make_unique<T>(arg) to construct a T from an arg without making any spurious copies. To do that, it is essential that the lvalue/rvalue distinction is maintained. Consider: auto p1 = make_unique<Xref<string>>(7,"Here");

"Here" is an rvalue, so forward(string&&) is called, passing along an rvalue, so that Xref(int,string&&) is called to move from the string holding "Here". The more interesting (subtle) case is: auto p2 = make_unique<Xref<string>>(9,x); Here, x is an lvalue, so forward(string&) is called, passing along an lvalue: forward()’s T is deduced to string& so that the return value becomes string& &&, which means string& (§7.7.3). Thus, Xref(int,string&) is called for the lvalue x, so that x is copied.

Stroustrup, Bjarne. The C++ Programming Language (p.689). Pearson Education. Kindle 版.
144デフォルトの名無しさん (ワッチョイ d55f-NNfd)
垢版 |
2022/11/16(水) 00:40:39.32ID:85X5ndMu0
C++ど素人なんですが、この画像のようなファイル群がある時に、Visual Studioでexe化するにはどうしたら良いですか?

まず、ファイルはsln形式などになってないですが、そういったものはつくる必要はなく、ExpressionApp.cppだけ開いてビルドボタンを押したりすれば良い感じなのでしょうか?
145デフォルトの名無しさん (ワッチョイ d55f-NNfd)
垢版 |
2022/11/16(水) 00:41:05.14ID:85X5ndMu0
>>144
すみません、画像を貼り忘れました
https://i.imgur.com/zn41rYL.png
2022/11/16(水) 00:41:14.43ID:Nbbm6FAB0
えぇ…禿さん耄碌してんなあ
2022/11/16(水) 00:41:57.33ID:Nbbm6FAB0
>>145
cmake使え
2022/11/16(水) 00:42:22.40ID:g3O9ReAZM
>>140
"Here" is an rvalue, so forward(string&&) is called, passing along an rvalue, so that Xref(int,string&&) is called to move from the string holding "Here".

>>141
テンプレート関数なので、Aという方引数が決定されるメカニズムが重要となります。
Aがstringに決定されたならば、文字列リテラルからstringへの変換法則はおなじみの
ものとなります。
それよりも、まず、どうしてAがstringに決定されたのかの「仕組み」が分かりません。
2022/11/16(水) 00:44:42.87ID:P8Ivr6rPa
>>144
プロジェクト作ればいいよ
2022/11/16(水) 00:50:02.83ID:g3O9ReAZM
>>143
142と143の間に、次の記述が挟まっています。
So:
string x {"There and back again"};
Xref<string> r1 {7,"Here"}; // r1 owns a copy of string{"Here"}
Xref<string> r2 {9,x}; // r2 just refers to x
Xref<string> r3 {3,new string{"There"}}; // r3 owns the string{"There"}

Here, r1 picks Xref(int,string&&) because x is an rvalue.
Similarly, r2 picks Xref(int,string&) because x is an lvalue.
Lvalues and rvalues are distinguished by template argument deduction:
an lvalue of type X is deduced as an X& and an rvalue as X.
This differs from the binding of values to non-template argument rvalue references (§12.2.1)
but is especially useful for argument forwarding (§35.5.1).
Consider writing a factory function that make Xrefs on the free store and returns
unique_ptrs to them:
151デフォルトの名無しさん (ワッチョイ d55f-NNfd)
垢版 |
2022/11/16(水) 00:50:03.82ID:85X5ndMu0
>>147
ありがとうございます
やってみます
2022/11/16(水) 00:51:20.49ID:eOApcCVI0
>>137
文字列リテラルが lvalue なのはややこしい解釈の余地はなく直接的に明記されている。
https://timsong-cpp.github.io/cppwp/n3337/expr.prim.general#1

少なくとも

> "Here"は右辺値なので

というのは確実に誤った記述だよ。
最初の段階で誤っているのだからそこから後の理屈の立て方に筋が通るはずがない。

>>148

A は string に決定されない。
そういう仕組みは無いのでそれを前提として考えるな。
2022/11/16(水) 01:10:00.99ID:g3O9ReAZM
>>152
>A は string に決定されない。
>そういう仕組みは無いのでそれを前提として考えるな。
なるほど。しかし、だとすれば、
「Consider: auto p1 = make_unique<Xref<string>>(7,"Here");
 "Here" is an rvalue, so forward(string&&) is called, passing along an rvalue,
 so that Xref(int,string&&) is called to move from the string holding "Here".」
の部分はどう説明できますか?
2022/11/16(水) 01:14:18.30ID:g3O9ReAZM
>>153
今思ったんですが、もしかしたら、
>Consider: auto p1 = make_unique<Xref<string>>(7,"Here");
の部分が、
Consider: auto p1 = make_unique<Xref<string>>(7,string{"Here"});
の書き間違いだったのかもしれませんね。

なお、直接関係有りませんが、>>150
>Xref<string> r1 {7,"Here"}; // r1 owns a copy of string{"Here"}
>Here, r1 picks Xref(int,string&&) because x is an rvalue.
は、確認しましたが、kindle版は確かに正確にこう書かれていますが、
このr1の定義部分に「x」は存在しておらず、代わりに"Here"が存在していますので
そこも書き間違いかも知れません。
2022/11/16(水) 01:26:05.39ID:g3O9ReAZM
もしくわ、
>auto p1 = make_unique<Xref<string>>(7,"Here");
は、
auto p1 = make_unique<Xref<string>,string>(7,"Here");
と書きたかったのでしょうか。つまり、もし、
auto p1 = make_unique<Xref<string>>(7,string{"Here"});
または、
auto p1 = make_unique<Xref<string>,string>(7,"Here");
と書いてあったならば、辻褄が合いそうです。
2022/11/16(水) 05:12:39.73ID:c3tWnPnh0
文字を反転させる関数を作っているのですがうまく行きません
voidの部分がおかしいと思うんですが正直手詰まりです
誰か解決策はありますでしょうか
実行するとrevarce関数が飛ばされて終了してしまいます

void revarse(char* p, char* r);
int main(void)
{
char str1[64];
char str2[64] = {};

printf("文字列を入力\n>>");
scanf("%s", str1);

revarse(str1, str2);

printf("%s", str2);

rewind(stdin);
getchar();
return 0;
}
//反転させる関数
void revarse(char* p, char* r)
{
int len = strlen(p);

for (int i = 0; i <= len / 2; i++)
{
*(r + i) = *(p + (len - i));
}
}
2022/11/16(水) 05:28:39.68ID:PEnRRRQh0
おい、もうテメーの日記帳に書いとけや
2022/11/16(水) 05:33:02.42ID:5+x4ry0S0
>>156
文字列pが "12345" だとして考えてみ?
len=5 だろ?

*(p + (len - i));

これって i=0 の時 *(p + (5 - 0)) => *(p + 5) ってことになる

ゼロベースだからインデックス5にはNULL文字'\0'が入っている
それを*r にコピーしている
つまりコピーされるのは常に長さ0の文字列
そりゃ出力したってなにも表示されないさ

あとlen / 2はおかしいだろ
練習するならマルチバイトはまず置いておいてシングルバイト文字のみ扱え
2022/11/16(水) 05:50:25.16ID:c3tWnPnh0
>>158
ありがとうございます!
助言道理に直したら無事に反転させることができました!
本当にありがとうございます!
精進します!
2022/11/16(水) 06:49:36.90ID:f7msq55Zd
実習問題臭いのが気になる
2022/11/16(水) 08:13:10.02ID:6xMrEJ8a0
int と N 要素の vector<double> から N+1 要素の tuple<int, double, double,...> を作る方法ってありますか
2022/11/16(水) 08:25:10.43ID:Nbbm6FAB0
Nがコンパイル時に決まってないと無理
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況