2017-09-21 5 views
0

この質問のタイトルが正しいかどうかはわかりません。私がしようとしていることはかなり辛いことです。私はそれを簡潔に表現する方法さえ知らないのです。申し訳ありません。未評価のコンテキストでクラスメンバーに適用されたメンバー関数の結果タイプを取得するにはどうすればいいですか

私はある種の「安全な」価値クラスに包まれた値のコンテナを持っています。そのコンテナへのポインタ、そのメンバの1つへの参照を取得する関数が必要です。

渡されたポインタが有効な場合、関数はラップされた値の中の値を返します。

ポインタがnullptrの場合、関数はデフォルトで作成された値を返します。

Anyhoo、ここではいくつかのコードです。私はあなたが

template <typename T, typename M, 
    typename R = typename std::remove_reference< 
        decltype(*(std::declval<M>()))>::type> 
R value_or_default (T * o, M T::*m) 
{ return o ? *(o->*m) : R{}; } 

を書くことができると仮定していますが、コンパイラができるので(T)オブジェクトの型をexplicating nullptrケースを呼び出す必要があり

template<typename T> 
class Wrapped { 
    T t{}; 
public: 
    T& operator*() { 
     return t; 
    } 
}; 

class Container { 
public: 
    Wrapped<int> i; 
    Wrapped<string> s; 
}; 

template <typename T, typename R, typename C> 
R value_or_default(T* object, Wrapped<R> C::* member) 
{ 
    return *((*object).*member); 
} 

template <typename R, typename C> 
R value_or_default(nullptr_t, Wrapped<R> C::*, R default_value = R{}) 
{ 
    return default_value; 
} 

int main() { 
    Container c; 
    auto actual_int = value_or_default(&c, &Container::i); // Returns *(c.i). 
    auto default_string = value_or_default(nullptr, &Container::s); // Returns string{}. 

    std::cout << actual_int << std::endl; 
    std::cout << default_string << std::endl; 
    return 0; 
} 
+0

機能タイプが、値を返すことはできません。 C++は強く型付けされているので、渡された関数の引数に基づいて戻り値の型を変更することはできません。 std :: variantがあなたを助けてくれるかもしれません(またはあなたが望むものをするかもしれません)。 –

+0

@ÖöTiibあなたが何を意味するか分かりません。私には、返される型が渡された引数に基づいている関数があります: 'template T foo(T);'。 – screwnut

+0

あなたの例のfooは関数ではありませんが、関数のテンプレートの宣言とテンプレート引数があります。 –

答えて

2

nullptrからそれを推測してください。

ので

Container c; 

auto actual_int = value_or_default(&c, &Container::i); // Returns *(c.i). 
auto default_string = value_or_default<Container>(nullptr, &Container::s); 
// ....................................^^^^^^^^^ 

static_assert(std::is_same<int, decltype(actual_int)>::value, "!"); 
static_assert(std::is_same<std::string, 
          decltype(default_string)>::value, "!"); 
1

:どの程度

template<typename T> 
class Wrapped { 
    T t; 
public: 
    T& operator*() { 
     return t; 
    } 
}; 

class Container { 
public: 
    Wrapped<int> i; 
    Wrapped<string> s; 
}; 

// Compiler error with R. 
// I'd like R to be the return type of invoking operator* on the member that's represented by M. 
// I've tried about 50 different versions of declarations to declare the type of R. This one feels like it most closely represents what I'm trying to achieve. 
// R should be the T in Wrapped<T>. 

template <typename T, typename M, typename R = decltype(declval<M>().operator*())> 
R value_or_default(T* object, M member, R default_value = R{}) 
{ 
    object ? *((*object).*member) : default_value; 
} 

Container c; 
auto actual_int = value_or_default(&c, &Container::i); // Returns *(c.i). 
auto default_string = value_or_default(nullptr, &Container::s); // Returns string{}. 
関連する問題