2017-01-09 20 views
4

私はenable_ifの使い方を学ぶ必要があります。このために、私はenable_ifを使ってdistance関数を再実装する必要があります。私はこれを試してみました:enable_ifの使い方は?

#include <iostream> 
#include <vector> 
#include <list> 
#include <utility> 
#include <type_traits> 

template<class In> 
typename std::enable_if<!std::is_random_acces_iterator<In>::value, std::iterator_traits<In>::difference_type>::type my_distance(In begin, In end, std::input_iterator_tag dummy){ 
    typename std::iterator_traits<In>::difference_type n = 0; 
    while(begin!=end){ 
    ++begin; ++n; 
    } 
    std::cout << "STEPPING" << std::endl; 
    return n; 
} 

template<class Ran> 
typename std::enable_if<std::is_random_acces_iterator<Ran>::value, std::iterator_traits<In>::difference_type>::type my_distance(Ran begin, Ran end, std::random_access_iterator_tag dummy){ 
    std::cout << "RANDOM" << std::endl; 
    return end - begin; 
} 

template <class I> inline 
typename std::iterator_traits<I>::difference_type my_distance_wrapper(I begin, I end){ 
    typedef typename std::iterator_traits<I>::iterator_category cat; 
    return my_distance(begin, end, cat()); 
} 

int main() { 
    std::vector<int> ve; 
    std::list<int> li; 
    for(int i = 0; i < 3; i++){ 
    ve.push_back(i); 
    li.push_back(i); 
    } 
    std::cout << my_distance_wrapper(ve.begin(), ve.end()) << std::endl; 
    std::cout << my_distance_wrapper(li.begin(), li.end()) << std::endl; 
    return 0; 
} 

私は私がtype_traitsを確認したが、何かが特定のイテレータであるかどうかをチェックするために何かを見つけることができませんでしたstd::is_pod<In>::value に似std::is_random_acces_iterator<In>::valueのようないくつかの機能を使用することにより、これを行うことができると思いました。 random_acces_iteratorが何かを確認するにはどうすればよいですか?

私の質問は基本的にどのようにテンプレートで関数fを行うのですか? enable_ifを使用することはできません。それは私の仕事の要件です。そして、関数fをそのテンプレートに入れることができたら、SFINAEが他の関数を正しく破棄すると確信するのは正しいですか?

template<typename iterator> 
using is_random_access_iterator = 
    std::is_same<typename std::iterator_traits<iterator>::iterator_category, 
       std::random_access_iterator_tag>; 

。ここで、その後

template<typename iterator> 
std::enable_if_t<is_random_access_iterator<iterator>::value, 
       typename std::iterator_traits<iterator>::difference_type> 
my_distance(iterator a, iterator b) { return a-b; } 

template<typename iterator> 
std::enable_if_t<!is_random_access_iterator<iterator>::value, 
       typename std::iterator_traits<iterator>::difference_type> 
my_distance(iterator a, iterator b) { /* ... */ } 

を次のように

答えて

5

あなたはstd::is_same<>タイプの特徴を使用することができ、std::enable_if_t<,>

template<bool condition, typename type = void> 
using enable_if_t = typename enable_if<condition,type>::type; 
として(C++ 14以降)定義されたヘルパーの別名であります

実際には、関数f()constexprと宣言し、enable_ifの中で直接使用することもできます。つまり、std::enable_if<f<It>(), ...>です。

+0

あなたのソリューションを使用しようとすると、「予想されるタイプ、取得済み」というメッセージが表示されます:<_Iterator> :: iterator_category '' – Hakaishin

+0

@Hakaishin大丈夫、私はそれをテストしませんでした。私は 'typename'を忘れました。 – Walter

+0

理由はわかりませんが、以前のコメントは編集できません。しかし、とにかくこの全体のメタプログラミングのことは、単にプログラミングを行うように思われますが、これらの内部にあります。私は潜在的な利益を見ますが、これらすべてのことを学ぶ価値があるかどうか、そして実際にどれくらい頻繁に使用されるのか自分自身に尋ねます。 – Hakaishin

関連する問題