質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

425閲覧

C++ における (double) x と static_cast<double>(x) と double(x) と double{x} の違い

Paalon

総合スコア266

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

0クリップ

投稿2024/11/13 18:14

C++ で数値型を変換するときにどの方法が良いのでしょうか?

定数表現について: Tdouble などとして、コンパイル時に a が決まるとき、(T) astatic_cast<T>(a)T(a)T{a} でどう違ってどれが良いのか?
変数表現について: Tdouble などとして、コンパイル時に x が決まらないとき、(T) xstatic_cast<T>(x)T(x)T{x} でどう違ってどれが良いのか?

fana👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nanashi123

2024/11/14 05:49 編集

Google翻訳では同等と訳されますね 原文のニュアンスは分かりませんが、翻訳側のニュアンスが少し曖昧なのは、{}がキャストの対象であるためと考えられます いずれにしてもT()では全ての型変換には対応できないので、整数型以外のキャストも想定する場合ば(T)としておくのが無難と思われます 尚質問内容を読み違えていた部分がありますが、static_cast<T>についてはこちらのリンクではdynamic_castの方が安全であると案内されています(https://learn.microsoft.com/ja-jp/cpp/cpp/static-cast-operator?view=msvc-170) もしstatic_castを用いる場合は、dynamic_castの検討をおすすめします
fana

2024/11/15 01:23

本件は数値型の変換に関する話なので,dynamic_cast は使えません.
Manabu

2024/11/15 22:25

ちょっと分かりにくいですが > dynamic_castはこちらにある通り~ オブジェクトのキャストを対象としたクラスです と最初にあるので、たぶんその部分は補足ではないでしょうか
guest

回答2

0

ベストアンサー

数値型の値から double に型変換するという文脈であればどれを使っても結果は同じです。 ただ、結果は同じでも変換の意図によって使い分けるのは良い考えです。

(T)a はキャスト記法、 T(a) は関数的記法のキャストです。 関数的記法に与えられる式がひとつである場合に限り効果はキャスト記法と全く同一です。 (仕様上、関数的記法は与えられる式がひとつの場合とふたつ以上の場合で場合分けされて挙動が記述されていることに注意してください。)

static_cast<T>(a) では型変換できる種類が限定されており比較的安全な種類の変換しか出来ませんが、数値型同士の変換はほとんどどれも可能なはずです。

T{a} の形式はリスト初期化によって初期化された値を生成するのですが、 T の種類によって効果が異なります。 数値型同士であれば他のキャストと同様と考えておおよそ問題ないと思いますが縮小変換を禁止しているというのが特徴です。 たとえば int{1.0} といったように double 型の値から int へ変換するといったようなことは出来ません。

投稿2024/11/14 02:39

SaitoAtsushi

総合スコア5675

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Paalon

2024/11/14 04:26

`std::int32_t x = 1;` として、`double{x}` とすると、`std::int32_t` で表せる数は全て `double` で厳密に表現可能なのに、縮小変換であるという警告が出るのはなぜでしょうか? ```cpp #include <print> #include <cstdint> int main() { using T = double; std::int32_t x = 1; std::println("{}", (T)x); std::println("{}", T(x)); std::println("{}", static_cast<T>(x)); std::println("{}", T{x}); } ``` ```bash $ g++-14 -std=c++23 -Wall -Wextra main.cpp -o main main.cpp: In function 'int main()': main.cpp:11:30: warning: narrowing conversion of 'x' from 'int32_t' {aka 'int'} to 'T' {aka 'double'} [-Wnarrowing] 11 | std::println("{}", T{x}); | ^ main.cpp:11:30: warning: narrowing conversion of 'x' from 'int32_t' {aka 'int'} to 'T' {aka 'double'} [-Wnarrowing] ```
SaitoAtsushi

2024/11/14 05:04

C++ の規則が言うところの縮小変換の定義では整数から浮動小数点への変換は一律に縮小変換であるということになっています。 https://timsong-cpp.github.io/cppwp/n3337/dcl.decl#dcl.init.list-7.3 そのように設計された意図に関する資料を私は見つけられないんですが、単にルールが煩雑になるのを嫌って一律に扱うことにしたんじゃないでしょうか。 ちなみに定数 (定数式) の場合は変換可能なこともあります。
guest

0

前半については誤認識でしたので取り下げます。

T(式)T{式}は、初期化専用の構文です。変数宣言・関数の引数・返り値など限られた場面でしか使えません。

数値型同士であれば、オーバーロードなどが発生する余地もありませんので、Cスタイルのキャスト((double))でもstatic_castでも動作は同じです。あとは、コーディングスタイルの問題になります。

投稿2024/11/13 22:48

編集2024/11/14 04:12
maisumakun

総合スコア145932

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Paalon

2024/11/14 02:21

①`型(表現)` や ②`型{表現}` に対して、③`(型) 表現` と ④`static_cast<型>(表現)` は限られていないということですか?何が限定されていないのでしょうか?よく分かりません。数値型の場合において、③と④は同じ意味ということですか?違う場合はどういう場合なのでしょうか?
Paalon

2024/11/14 02:25

加えて、「コーディングスタイルの問題」というのは、③と④の意味が同一だから③と④の選択はコーディングスタイルの問題ということですか?それとも①と②と③と④からの選択がコーディングスタイルの問題ということですか?
maisumakun

2024/11/14 04:13

前半は自身の誤認識でしたので取り下げます。 SaitoAtsushiさんの回答のほうがずっと適切なので、そちらを参照してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問