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

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

ただいまの
回答率

91.34%

  • C++

    2434questions

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

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

解決済

回答 1

投稿 2017/05/07 21:45

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

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.34%

関連した質問

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

  • C++

    2434questions

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