2016-11-01 8 views
3

を返す関数の型を取得できません。私はクラスのプロパティシステムを使用しようとしているconstexprの自動

プロパティを一意に識別するための対応するメンバーポインタ、名前及び(列挙から)INTを有します。ここで

は、プロパティを定義するコードは次のとおりです。

template<typename Class, typename T> 
struct MemberProperty 
{ 
    constexpr MemberProperty(T Class::*aMember, const char* aName, int aId) 
    : member(aMember), name(aName), id(aId) 
    {} 

    T Class::*member; 
    const char* name; 
    int id; 
}; 

私は、この関数を呼び出してプロパティを作成します。

template <typename Class, typename T> 
constexpr auto makeProperty(T Class::*member, const char* name, int id) { 
    return MemberProperty<Class, T>{member, name, id}; 
} 

は、私の目標は、このようなクラスのプロパティを定義することです:

class User 
{ 
public: 
    enum PropertiesEnum 
    { 
     Property_Name 
    }; 

    string m_name; 

    static constexpr auto Properties() { 
     return std::make_tuple(
      makeProperty(&User::m_name, "name", User::Property_Name) 
     ); 
    } 

    using PropertiesType = decltype(Properties()); 

    //PropertyManager<PropertiesType> m_propertyManager; 
}; 

私は宣言する行のコメントを解除できるようにしたいと思いますm_propertyManager 。 これはコンパイルされないという問題があります。グラム++では、私が取得:

error: use of 'static constexpr auto User::Properties()' before deduction of 'auto'

のVisual Studio 2015では、私が取得:

error C3779: 'User::UserProperties': a function that returns 'auto' cannot be used before it is defined

がどのように私はこの作業を行うことができますか?それは世俗的な依存関係のように見えますが、私はそれを動作させる方法を見つけることができません。私はそれが[class.mem]/6によるものだと思い

http://coliru.stacked-crooked.com/a/24e7f5ea7f83da6f

+2

宣言の中で、 ' - > decltype(std :: make_tuple(makeProperty(&User :: m_name、" name "、User :: Property_Name)))'が助けてくれたと思う... [ライブデモ](http:// coliru.stacked-crooked.com/a/a7f291a384992464) –

+1

ありがとうございました。しかし、別の方法がありますか? make_tupleのパラメータは潜在的に非常に大きいです(私は多くのプロパティを追加します)。 – Michael

+1

私は通常、これらの繰り返しを避けるためにMACROを使います。 } ' – Jarod42

答えて

4

: はここでの例です。
はそれはのように述べている:

A class is considered a completely-defined object type ([basic.types]) (or complete type) at the closing } of the class-specifier. [...]

注あなたの特定のケースのための最後の文:

[...] Otherwise it is regarded as incomplete within its own class member-specification.

エイリアス宣言は、メンバー仕様の一部とみなされ、(私が言わせ)に記載されていませんルールの例外:

:少しあなたの例をさらに削減することにより

[...] Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and default member initializers (including such things in nested classes). [...]

は、我々はこれを持っています

struct S { 
    auto f() {} 
    using T = decltype(f()); 
}; 

int main() {} 

エラーが多かれ少なかれ同じです。

上述したように使用して宣言で、クラスは、このようにそのメンバ関数ではない、完全に定義されたタイプとは見なされません。
そのため、メンバ関数の戻り値型の控除が行えず、使用宣言を満たすことができません。コンパイラは関数の定義でを見なければならない戻り値の型を推論する
注意、それはその本体です。他の点では

、それははるかにこれをやってから(概念的には)ありません。

auto f(); 
using T = decltype(f()); 
int main() {} 

あなたはまだ定義されていない機能の戻り値の型を評価するにはどうすればよいですか?
できません。上記のコードは実際には機能しません。

メンバー関数がconstexprであるという事実は、この場合は何も変更されません。質問へのコメントで述べたように


は、明示的に問題を回避するために、末尾の戻り値の型によって、戻り値の型を指定することができます。
この場合、定義は必要なくなり、宣言から戻り値の型を取得することができます。実際には、返品タイプについては全く控除はありません。

関連する問題