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

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

ただいまの
回答率

91.74%

  • C++

    2180questions

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

C++:自クラスの型にアクセスできる方法はないでしょうか?

解決済

回答 1

投稿 2017/05/07 21:45

  • 評価
  • クリップ 0
  • VIEW 268

Chironian

C++総合1位

クラスの中のメンバ関数の外で自分のクラス名を使わずに、自分のクラスの型をアクセスしたいです。

メンバ関数の中であれば、decltype(*this)を使ってできます。

#include <iostream>
#include <type_traits>
struct Foo
{
    Foo()
    {
        typedef typename std::remove_reference<decltype(*this)>::type This;
        std::cout << std::is_same<This, Foo>::value << std::endl;
    }
};

int main()
{
    Foo foo;
}

メンバ関数の外で上記のようにFooを使わずにThisを定義する術はないでしょうか?

struct Foo
{
    // メンバ関数の外のここでFooを使わずにThisを定義したい。
    typedef ????? This;

      :
    Foo()
    {
        typedef typename std::remove_reference<decltype(*this)>::type This;
        std::cout << std::is_same<This, Foo>::value << std::endl;
    }
};
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

関数戻り値型推論を利用する案はいかがでしょう。

struct Foo {
  static auto ThisTypeHelper() -> std::remove_reference_t<decltype(*this)>;
  using This = decltype(ThisTypeHelper());
  //...
};

Demo: https://wandbox.org/permlink/KE2Y3rrXjRdKwxjA


追記: 上記コードはGCCで通りますが、Clangではエラーになります。

StackOverflowに同じトピック"Can I implement an autonomous self member type in C++?"があり、どうもC++14(C++1z/17でも?)現在は実現不可能な気がしてきました。

C++14(N3937) [expr.prim.general]/paragraph 3によれば、thisキーワードをstaticメンバ関数の宣言中で用いるのはNGと読めます(太字部)。C++1z/17(N4659)では[expr.prim.this]/p2。

If a declaration declares a member function or member function template of a class X, the expression this is a prvalue of type "pointer to cv-qualifier-seq X" [...] It shall not appear before the optional cv-qualifier-seq and it shall not appear within the declaration of a static member function (although its type and value category are defined within a static member function as they are within a non-static member function). [...]

投稿 2017/05/07 23:27

編集 2017/05/08 10:12

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2017/05/08 00:13 編集

    ご回答ありがとうございます。

    C++14ならできるのですね!!

    メンバ関数の外で*thisを書けることにびっくりです。
    struct Foo
    {
     typedef typename std::remove_reference<decltype(*this)>::type This;
     typedef typename decltype(Foo()) This;
    };
    とすると、前者は"error: invalid use of 'this' at top level"、後者は"invalid use of incomplete type"となるから、半ば諦めてました。それだけに、ありがたいです。

    今、開発しているTheolizer(https://github.com/yossi-tahara/Theolizer)はC++11で開発してますが、C++14なら無駄にクラス名を書かなくて良くなるのです。具体的な対応方法を検討します。
    もう一度、ありがとうございました。

    キャンセル

  • 2017/05/08 00:43

    よく見たら、C++11でも可能でした。やった!
    https://wandbox.org/permlink/3epK4B6N89sxMUiy

    キャンセル

  • 2017/05/08 14:29

    yohhoyさん。

    追記、ありがとうございます。標準規格上どうなのか気になってました。やはり、規格的にはダメっぽいですね。static関数でthisにアクセスできるっておかしいですしね。意味的には納得です。
    ただ、Visual C++でも通りましたのでちょっと悩ましいのですが、clangでエラーなら恐らく使えないです。(Theolizerは構文解析にclangのlibToolingを使っているため。)

    ところで、ご提案頂いた方法のポイントは「戻り値を後置する構文」ですね。これはC++11で規定されているようです。
    https://cpprefjp.github.io/lang/cpp11/trailing_return_types.html

    キャンセル

  • 2017/05/08 23:15

    おっしゃる通り「auto f() -> 戻り値型」はC++11から有効でした。
    C++14で追加されたのは本体return文からの戻り値型推論でした。

    キャンセル

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

ただいまの回答率

91.74%

関連した質問

  • 解決済

    C++:配列型(サイズ含む)へのポインタをnewで生成したい

    C/C++の配列へのポインタは要素へのポインタにて代用される場合が多いです。(int foo[3];とした時、fooはint型へのポインタとなる等。) しかし、C++の場合、

  • 解決済

    templateを使って異なるクラスのインスタンスを作成したい

    前提・実現したいこと 異なる型のインスタンスを作成する関数を作成しています。 作成する型が異なる以外はすべて処理が同じためtemplate関数を使用して実装を共通化しようとして

  • 解決済

    整数のオーバーフローを防ぐには

    2数 MIN, MAX (MIN < MAX)が与えられた時に a(MIN) = MIN, a(MAX) = MAXとなる数列 a(i) = ..., MAX - 2, M

  • 解決済

    配列の中身を個別に抜き出したい。C++

    配列の中身を、1つずつ抜き出す関数を作りたいのですが、方法がおもいつきません 具体的には、以下のようなものになります void SET(){ int a[] = {1, 2

  • 解決済

    C++11のrandomの種

    C/C++ ( いわゆる BetterC ) でやっています。 "C 標準の srand/rand で乱数発行は あまりよくない" というサイトページを何度か見かけたことがあ

  • 解決済

    可変長引数テンプレートが思うように展開されない

    発生している問題 可変長テンプレートを使い、引数から受け取った変数を用いて配列の初期化を行おうとしたのですが、 配列の中身が全て0になってしまいました。 どうすれば関数に

  • 解決済

    C++ デフォルトコンストラクタについて

    現在、C++の参考書のデフォルトコンストラクタの項目でつまづいています。 以下、参考書からの抜粋 ========== デフォルトコンストラクタは自分で定義しなければ勝手

  • 解決済

    c[c++] テンプレート関数の特殊化について

    こんばんは。テンプレート関数の特殊化についてわからない部分があるので、教えてください。 テンプレート関数の特殊化の例として、以下のようなものが書けますが、 #include

同じタグがついた質問を見る

  • C++

    2180questions

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