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

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

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

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

Q&A

解決済

2回答

558閲覧

assert文に相当するoperator文の引数の型

Y.R.T

総合スコア42

C++

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

0グッド

0クリップ

投稿2020/09/01 06:26

下記構文で、main関数のassert(t1 == tc);は
operator文の

template <scale S> inline bool operator==(quantity<S> const& lhs, quantity<S> const& rhs) { return are_equal(static_cast<double>(lhs), static_cast<double>(rhs)); }

に相当するのは分かるのですが、引数二つの型が<S>なのが
どうしてなのかがわかりません。
ここは<R>ではないのですか?
構文からは<S>を<R>にキャストしているように見えるのですが。

#include <cmath> #include <assert.h> bool are_equal(double const d1, double const d2, double const epsilon = 0.001) { return std::fabs(d1 - d2) < epsilon; } namespace temperature { enum class scale { celsius, fahrenheit, kelvin }; template <scale S> class quantity { const double amount; public: constexpr explicit quantity(double const a) : amount(a) {} explicit operator double() const { return amount; } }; template <scale S> inline bool operator==(quantity<S> const& lhs, quantity<S> const& rhs) { return are_equal(static_cast<double>(lhs), static_cast<double>(rhs)); } template <scale S> inline bool operator!=(quantity<S> const& lhs, quantity<S> const& rhs) { return !(lhs == rhs); } template <scale S> inline bool operator< (quantity<S> const& lhs, quantity<S> const& rhs) { return static_cast<double>(lhs) < static_cast<double>(rhs); } template <scale S> inline bool operator> (quantity<S> const& lhs, quantity<S> const& rhs) { return rhs < lhs; } template <scale S> inline bool operator<=(quantity<S> const& lhs, quantity<S> const& rhs) { return !(lhs > rhs); } template <scale S> inline bool operator>=(quantity<S> const& lhs, quantity<S> const& rhs) { return !(lhs < rhs); } template <scale S> constexpr quantity<S> operator+(quantity<S> const& q1, quantity<S> const& q2) { return quantity<S>(static_cast<double>(q1) + static_cast<double>(q2)); } template <scale S> constexpr quantity<S> operator-(quantity<S> const& q1, quantity<S> const& q2) { return quantity<S>(static_cast<double>(q1) - static_cast<double>(q2)); } template <scale S, scale R> struct conversion_traits { static double convert(double const value) = delete; }; template <> struct conversion_traits<scale::celsius, scale::kelvin> { static double convert(double const value) { return value + 273.15; } }; template <> struct conversion_traits<scale::kelvin, scale::celsius> { static double convert(double const value) { return value - 273.15; } }; template <> struct conversion_traits<scale::celsius, scale::fahrenheit> { static double convert(double const value) { return (value * 9) / 5 + 32;; } }; template <> struct conversion_traits<scale::fahrenheit, scale::celsius> { static double convert(double const value) { return (value - 32) * 5 / 9; } }; template <> struct conversion_traits<scale::fahrenheit, scale::kelvin> { static double convert(double const value) { return (value + 459.67) * 5 / 9; } }; template <> struct conversion_traits<scale::kelvin, scale::fahrenheit> { static double convert(double const value) { return (value * 9) / 5 - 459.67; } }; template <scale R, scale S> constexpr quantity<R> temperature_cast(quantity<S> const q) { return quantity<R>(conversion_traits<S, R>::convert(static_cast<double>(q))); } namespace temperature_scale_literals { constexpr quantity<scale::celsius> operator "" _deg(long double const amount) { return quantity<scale::celsius> {static_cast<double>(amount)}; } constexpr quantity<scale::fahrenheit> operator "" _f(long double const amount) { return quantity<scale::fahrenheit> {static_cast<double>(amount)}; } constexpr quantity<scale::kelvin> operator "" _k(long double const amount) { return quantity<scale::kelvin> {static_cast<double>(amount)}; } } } int main() { using namespace temperature; using namespace temperature_scale_literals; auto t1{ 36.5_deg }; auto t2{ 79.0_f }; auto t3{ 100.0_k }; { auto tf = temperature_cast<scale::fahrenheit>(t1); auto tc = temperature_cast<scale::celsius>(tf); assert(t1 == tc); } { auto tk = temperature_cast<scale::kelvin>(t1); auto tc = temperature_cast<scale::celsius>(tk); assert(t1 == tc); } { auto tc = temperature_cast<scale::celsius>(t2); auto tf = temperature_cast<scale::fahrenheit>(tc); assert(t2 == tf); } { auto tk = temperature_cast<scale::kelvin>(t2); auto tf = temperature_cast<scale::fahrenheit>(tk); assert(t2 == tf); } { auto tc = temperature_cast<scale::celsius>(t3); auto tk = temperature_cast<scale::kelvin>(tc); assert(t3 == tk); } { auto tf = temperature_cast<scale::fahrenheit>(t3); auto tk = temperature_cast<scale::kelvin>(tf); assert(t3 == tk); } }

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

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

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

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

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

guest

回答2

0

ベストアンサー

引数二つの型

型はscaleです。
SもRもtemplate引数の名前にすぎませんので

c++

1template <int X> 2int func1(){ return X; } 3 4template <int Y> 5int func2(){ return func1<Y>(); }

c++

1int func1(int X){ return X; } 2int func2(int Y){ return func1(Y); }

と、ほぼ等価みたいな感じです。

投稿2020/09/01 06:52

asm

総合スコア15147

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

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

Y.R.T

2020/09/01 07:23

ありがとうございます。 理解出来ました。
guest

0

引数二つの型が<S>なのがどうしてなのかがわかりません。

単に「同じscale Squantity<S>==で比較できる」としているだけです。もちろん、「違うscale Squantity<S>同士も比較できるようにしたい」のであれば、template <scale S, scale R>operator ==を実装することも可能です。

構文からは<S>を<R>にキャストしているように見えるのですが。

どの部分がそう見えたのでしょうか。

投稿2020/09/01 06:36

maisumakun

総合スコア145184

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

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

Y.R.T

2020/09/01 06:48

template <scale R, scale S> constexpr quantity<R> temperature_cast(quantity<S> const q) { return quantity<R>(conversion_traits<S, R>::convert(static_cast<double>(q))); } の部分は、<S>を<R>にキャストしているのではないですか? main関数の { auto tf = temperature_cast<scale::fahrenheit>(t1); auto tc = temperature_cast<scale::celsius>(tf); assert(t1 == tc); } では、tcの型はquantity<R>かと思います。 t1は、quantity<scale::celsius>等に相当し 型はquantity<S>になるかと思います。 すみません、質問が少し変わりますね。 そう考えたら、assert文に相当する Operator文は、 template <scale S> inline bool operator==(quantity<S> const& lhs, quantity<S> const& rhs) { return are_equal(static_cast<double>(lhs), static_cast<double>(rhs)); } ではなく、 template <scale S> inline bool operator==(quantity<R> const& lhs, quantity<S> const& rhs) { return are_equal(static_cast<double>(lhs), static_cast<double>(rhs)); } になりませんか?
maisumakun

2020/09/01 06:54 編集

> (前略)の部分は、<S>を<R>にキャストしているのではないですか? すみません、明示されたoperator==の範囲外だとは思いませんでした。 > template <scale S> inline bool operator==(quantity<R> const& lhs, quantity<S> const& rhs) { return are_equal(static_cast<double>(lhs), static_cast<double>(rhs)); } になりませんか? なりません。その形では、Rが何者なのか決まらないです(Rも型パラメータにするなら、上に回答したとおり、そのような実装も可能です)。
maisumakun

2020/09/01 06:55

> tcの型はquantity<R>かと思います。 この考え方がおかしいです。RやSは「その場の状況に応じて決まる」もので、コード全体で1つのものと対応するわけではありません。
Y.R.T

2020/09/01 07:24

ありがとうございます。 理解出来ました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問