2016-04-29 13 views
2

私はこれを実行できるようにしたいと思います。特にテストがまたは寸法(今のところ)1または2のために反復可能ではないかもしれないかもしれないカスタムクラスを受け入れるようにテンプレート化されテンプレートを使用してファンクションメソッドが存在するかどうか再帰的にチェックしてください。

vector<int> p = {1, 2}; 
vector<vector<int>> q = {p, {0, 1}}; 

auto t = test(p); 
auto u = test(q); // Fails with below implementation 

。私は何が与えられたものがsize機能を持っているかどうかをチェックすることによって何をすべきかを決定しようとしています。

template<typename T> struct hasSize { 
    template<typename U, size_t(U::*)() const> struct SFINAE {}; 
    template<typename U> static char Test(SFINAE<U, &U::size>*); 
    template<typename U> static int Test(...); 

    static const bool value = sizeof(Test<T>(0)) == sizeof(char); 
}; 

template<typename iterable> int test(const iterable &x, std::false_type) { 
    return (int) x; 
} 

template<typename iterable> int test(const iterable &x, std:: true_type) { 
    int total = 0; 

    for(auto &each : x) 
     total += test(each, 
      std::integral_constant<bool, hasSize<decltype(each)>::value>()); 

    return total; 
} 

template<typename iterable> int test(const iterable &view) { 
    return test(view, std::true_type()); 
} 

ことがメンバ変数ではなく、機能にのみ適用されるように見えたので、私は、this答えにあきらめた後here与えられた回答にhasSizeをベース。私もhas_const_reference_opの修正版を最初の議論で試しましたが、これは同じ問題を抱えています。

このエラーは、SNIFAEが2回適用されないことを示しています。

error C2440: 'type cast': 
    cannot convert from 'const std::vector<int, std::allocator<_Ty>>' to 'int' 
note: No user-defined-conversion operator available that can perform this conversion, 
    or the operator cannot be called 
note: see reference to function template instantiation 
    'int test<iterable>(const iterable &, std::false_type)' being compiled 
with iterable = std::vector<int,std::allocator<int>> 

しかし、私には理由が分かりません。それはsizeメンバ関数のためのSFINAEチェックに失敗した参照型を生み出す -

+0

おそらく 'hasSize :: type> :: value>()' –

+0

のほうがいいかもしれませんが、それ以上のことをする必要があると思います型がネストされたコンテナで構成されているかどうかを判断する 'size()'関数の存在をチェックしてください。たとえば、文字列クラスには 'size()'関数があります。 –

答えて

1

それが失敗した理由は、auto& -typed変数の型const vector<vector<int>>&iterableで実際にタイプconst std::vector<int>&のある、そしてdecltypeで問い合せるときにということです存在。 decltypeによって生成タイプから

total += test(each, std::integral_constant<bool, 
         hasSize<typename iterable::value_type>::value 
//        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ 
        >()); 

または削除referenceness/const性:だからではなく、decltypeを使用しての、ちょうどvalue_typeiterableからを読んで、すべての

total += test(each, std::integral_constant<bool, 
         hasSize<typename std::decay<decltype(each)>::type>::value 
//          ~~~~~~~~~^ 
        >()); 
+0

非常に最小限の変更で動作しますが、 'const std :: vector 'という型の変数がサイズメンバを持たないと思われる理由はわかりません。あなたは詳しく説明できますか? – Meeuwisse

+0

@Meeuwisse参照型は参照型が指す型とは異なる型ですが、ポインタのようにju​​srはポインタにメンバ関数がありますか? –

0

まず、これは正しいことではありません以下のためのtest()一般:

template<typename iterable> int test(const iterable &view) { 
    return test(view, std::true_type()); 
} 

一般test ISNであるため」 t iterable - それは私たちがテストするために必要なものです!だからではなく、我々は、我々は見つけるために必要なすべてを見つけるために、ADLを利用できるように、名前空間の三つの機能のシリーズにこれを転送するつもりだ:

namespace adl { 
    struct helper {}; 

    template<typename iterable> 
    int test(helper, const iterable &x, std::false_type) { 
     return (int) x; 
    } 

    template<typename iterable> 
    int test(helper, const iterable &x, std:: true_type) { 
     int total = 0; 

     for(auto &each : x) { 
      // this calls the general one 
      total += test(helper{}, each); 
     } 

     return total; 
    } 

    template <typename iterable> 
    int test(helper, const iterable& x) { 
     return test(helper{}, x, std::integral_constant<bool, hasSize<iterable>::value>{}); 
    } 
} 

template<typename iterable> 
int test(const iterable &view) { 
    return test(adl::helper{}, view); 
} 

の各ように、私たちは、ADLを必要とします関数はお互いを見つけることができます。


単なる値ではなく型をもたらす型特性を書く方が良いことに注意してください。その後、私たちのテスターの過負荷が大幅に短くすることができます

template <class T, class = void> 
struct hasSize : std::false_type { }; 

template <class T> 
struct hasSize<T, void_t<decltype(std::declval<T const&>().size())>> 
: std::true_type { }; 

template <typename iterable> 
int test(helper, const iterable& x) { 
    return test(helper{}, x, hasSize<iterable>{}); 
} 

これはVS2013では動作しないかもしれませんが、あなたはまだhasSizetypeのtypedefを追加することができ、我々は次のように書いていました。

関連する問題