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

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

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

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

Q&A

解決済

1回答

2354閲覧

using typenameについて

apa

総合スコア68

C++

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

0グッド

0クリップ

投稿2020/07/23 01:48

とあるサイトをみて継承されたクラスでテンプレート型を使おうとすると
using typenameが必要であることを知りました。
using単体では何がしたいかはわかりますが、
ここにtypenameがつくとどういった意味をもつことになるのでしょうか?
(using typenameどちらを外しても正常にビルドできなかったため必須でした)
この2つを取り扱っているサイトがありませんでしたので、教えていただけたらと思っております!

下記
あるサイトをもとに作ったプログラム

template<typename T>
class A
{
public:
using value = T;
};

template<typename T>
class B : public A<T>
{
public:
using typename A<T>::value;
auto get() { return value; }
};

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

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

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

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

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

guest

回答1

0

ベストアンサー

クラステンプレート内で定義されている型 (この場合は value) が型の名前であるということはテンプレートを展開するまでわかりません。 T が具体的な型ではないのでこの時点では A<T> はまだ展開されておらず、 value が型であるということがわからないのです。

ですから、 value が型名であることを陽に指定する必要があり、それが typename を付ける理由です。 using typename という指定があるのではなく、 typenamevalue にかかっている指定なのです。

投稿2020/07/23 05:09

SaitoAtsushi

総合スコア5684

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

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

apa

2020/07/23 06:06

返信ありがとうございます。 Two phase name lookupという使用上あらかじめ定義しておくことは理解できるですが typenameでこれが型です! と指定してもなぜわざわざusingが必要なのかわかりません。 usingの能力は、別名をつける、名前空間を省略するために使うの2種類だと思いますが, こちらのプログラムでは名前空間の省略に用いられているとかんじまして typename A<T>::value; auto get() { return A<T>value; } このようにもためしてみましたがエラーを吐いてしまいます。 ここでのusingは上記2つの活用方法とは別の方法が取り入れられているのでしょうか?
SaitoAtsushi

2020/07/23 06:18

> typename A<T>::value; これはどういう意味のある文のつもりなんでしょうか。 型名だけがここにあってもエラーなのは当たり前だと思いますが……。 > auto get() { return A<T>value; } セミコロンが抜けていますね。 それと、ここも型名だけあっても意味のある式になりませんが、 おそらく A<T>value ではなく A<T>::value() ということが言いたいのでしょうか?
apa

2020/07/23 06:37

ほんとですね完全に抜けていました すいません! typename A<T>::value; に関しては自分でもよくわかりませんが、 ただusingの目的とはあっていないように思いまして変更してみた所存です。
SaitoAtsushi

2020/07/23 06:45

型名は型名であると同時にコンストラクタ (その型のオブジェクトを生成する関数) の名前でもあります。 質問者が見た「とあるサイト」では value は引数をひとつ以上受け取るコンストラクタを持っていませんでしたか? 名前空間修飾を省略できるという理解は正しいんですが、名前空間を省略できるようになった結果として同じ名前が現在の名前空間にあったときに衝突してしまう可能性があります。 その衝突はオーバーロードの解決ルールが適用されるので普通は引数がない関数では解決不能です。 逆に言えば適切に使えばオーバーロードを利用して自動的に必要な関数を選択させることに使えるテクニックです。
SaitoAtsushi

2020/07/23 07:09

例えば 以下のような例があったとき、 using foo::bar と書いてあるからといって bar の呼び出しで foo::bar が必ず使われるというわけではなくて、オーバーロードの解決ルールに従って選択されます。 完全な名前空間修飾をする場合と using を使う場合ではこのような差があるわけです。 #include <iostream> #include <string> namespace foo { int bar(int) { return 1; } }; int bar(const std::string&) { return 2; } using foo::bar; int main(void) { std::cout << bar(1) << std::endl; std::cout << bar("abc") << std::endl; return 0; }
apa

2020/07/23 07:49

template<typename T> struct foo_t { typedef T value_type; value_type value; }; template<typename T> struct cfoo : public foo_t<T> { using typename foo_t<T>::value_type; using foo_t<T>::value; value_type get_value() const { return value; } void set_value( value_type value_new ){ value = value_new; } }; int main(){ cfoo<int> foo; foo.set_value( 1 ); debug_printf( "%d\n", foo.get_value()); return 0; } 自分が見たプログラムは上記です サイト名 https://prettysoft.hatenablog.com/entry/20101128/1497356882 難しいですね。 もう少し整理してみます。
SaitoAtsushi

2020/07/23 08:26 編集

その参考にしたサイトの例では value に完全な名前空間修飾をしても using した場合と特に差はありません (実際に名前空間修飾でも大丈夫という例も提示されています) が、単に using の使用例として出したんでしょう。 using は名前空間修飾を省略できるようにする効果は結果的にはありますが、省略できるようにするというよりは指定したものを現在の名前空間に持ち込むというような意味合いで考えるとわかりやすいかと思います。
apa

2020/07/25 03:51

返信おくれました なるほどたしかにstruct内も名前空間になるんですね usingはそう考えると理解できた気がします! typenameはまだ理解しきれていないので勉強しようと思います 回答ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問