2017-01-11 4 views
3

私はテンプレートクラスbooのためにoperator|を書こうとしていますが、テンプレートクラスがブースト範囲タイプ(例:boost::range::filter_range - adlはローカルのものよりboost::range_detail::operator|(SinglePassRange& r, const replace_holder<T>)を好む)のようになるまではすべてうまくいきます。なぜadlは 'boost :: range_detail :: operator |'を好むのですか?ローカル '演算子|'を介して?

adlがローカルネームスペース上のこの詳細なネームスペースをブーストからオーバーロードする方が好きな理由を説明できる人はいますか?

#include <vector> 
#include <boost/range/adaptors.hpp> 

namespace local 
{ 
    template<typename T> 
    struct boo {}; 

    // this overload is not prefered when T is a boost::range::xxx_range 
    template<typename T, typename U> 
    auto operator|(boo<T>, U) 
    { 
     return false; 
    } 

    void finds_local_operator_overload() 
    { 
     std::vector<int> xs; 

     // works like expected and calls local::operator| 
     auto f = boo<decltype(xs)>{} | xs; 
    } 

    void prefers_boost_range_detail_replaced_operator_overload_instead_of_local_operator() 
    { 
     std::vector<int> xs; 
     // compiler error because it tries to call 'boost::range_detail::operator|' 
     auto filtered = xs | boost::adaptors::filtered([](auto &&x){ return x % 2; }); 
     auto f = boo<decltype(filtered)>{} | xs; 
    } 

}

打ち鳴らすエラー(ほぼ同じMSVCレポート):ADLのルールによれば

/xxx/../../thirdparty/boost/1.60.0/dist/boost/range/value_type.hpp:26:70: error: no type named 'type' in 
     'boost::range_iterator<local::boo<boost::range_detail::filtered_range<(lambda at 
     /xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > >, void>' 
    struct range_value : iterator_value< typename range_iterator<T>::type > 
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~ 
/xxx/../../thirdparty/boost/1.60.0/dist/boost/range/adaptor/replaced.hpp:122:40: note: in instantiation of template class 
     'boost::range_value<local::boo<boost::range_detail::filtered_range<(lambda at 
     /xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > > >' requested 
     here 
       BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>& f) 
            ^
/xxx/Tests.cpp:222:37: note: while substituting deduced template arguments into 
     function template 'operator|' [with SinglePassRange = local::boo<boost::range_detail::filtered_range<(lambda at 
     /xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > >] 
     auto f = boo<decltype(filtered)>{} | xs; 
+1

オペレータを考慮する必要があります。私はブーストのものがあなたのものよりも専門的だと思う。 – Jarod42

+0

'boost :: range_detail :: replace_holder'テンプレート関数はなぜ考慮されていますか? boost名前空間を開く引数はありません。 ブースト空間からのテンプレート 'T'のみが存在します。 それを考慮する十分な理由がある場合、なぜ他のブースト範囲ホルダーテンプレート関数も考慮されていないのですか? – TimW

答えて

2

boo<decltype(filtered)>{} | xsための過負荷のためにセットで添加 名前空間およびクラスlocalあります(booの場合)、boost::range_detaildecltype(filtered)の場合)およびstdstd::vector<int>xsの場合)。我々が持っているので、

template <class SinglePassRange> 
replaced_range<const SinglePassRange> 
operator|(
    const SinglePassRange&, 
    const replace_holder<typename range_value<SinglePassRange>::type>&); 

(あなたが期待するとおり、あなたのlocal

template<typename T, typename U> auto operator|(boo<T>, U); 

とで)

boost::range_detailでは問題1を:私たちは特殊性を持っている

推測されていないrange_value<boo<decltype(filtered)>>::typeハードエラー(このメソッドは、残念ながら、SFINAEではオーバーロードセットから削除されていません)。

overload_resolutionより前にエラーが発生します。

+0

cppreferenceには、 'class template specialization'と書かれている文章に多少の曖昧さがあるようです。この場合、 'boo 'は特殊化されていませんが、_instantiation_というクラステンプレートです。 – xtofl

+2

@xtoflそれは特殊化です(specailizationに名前を付ける* simple-template-id *)。プログラムでのその使用は、14.7.1 [temp.inst]ごとに(暗黙の) – Cubbi

関連する問題