2016-03-15 46 views
2

当参数不符合各种标准时,从类接口中选择性删除模板成员函数的原理是什么,用enable_if等进行了测试?如果留下了成员函数模板,试图使用它们将会失败,在我看来,在更复杂的情况下,使用比“替换失败”更有用的编译器错误?为什么boost/etc在模板成员函数的参数类型上做了太多的SFINAE?

如果编译失败,那么赞成这些极其严格的基于SFINAE的模板成员函数需求的理由是什么?

回答

4

编译器错误模板代码中的2-5深度已被发现几乎无法穿透。你会得到一些模板噪音。

SFINAE替代失败通常列出一个模板,并说它不起作用,因为一些参数不能推断,通常与显示失败的特征。不完美,但比模板更好。

此外,这些模板可以阻止其他有效的模板。另外,如果您使用类似SFINAE的技术,您可以测试给定的方法是否存在并且在编译时有效;如果身体未能编译,则不能。

+0

也可避免含糊不清,例如当初始化变体等(你几乎可以用“可以阻止其他有效的”来表示) – sehe

2

您发现哪些错误信息更易于理解。这一个与SFINAE?

template <class C, class = decltype(begin(std::declval<C&>())[0])> 
void sort_sfinae(C& c) { 
    std::sort(c.begin(), c.end()); 
} 

main.cpp: In function 'int main()': 
main.cpp:11:18: error: no matching function for call to 'sort_sfinae(std::__cxx11::list<int>&)' 
    sort_sfinae(l); 
       ^
main.cpp:5:6: note: candidate: template<class C, class> void sort_sfinae(C&) 
void sort_sfinae(C& c) { 
    ^
main.cpp:5:6: note: template argument deduction/substitution failed: 
main.cpp:4:62: error: no match for 'operator[]' (operand types are 'std::__cxx11::list<int>::iterator {aka std::_List_iterator<int>}' and 'int') 
template <class C, class = decltype(begin(std::declval<C&>())[0])> 
                  ^

或者这样一个没有?

template <class C> 
void sort_no_sfinae(C& c) { 
    std::sort(c.begin(), c.end()); 
} 

In file included from /usr/local/include/c++/5.3.0/algorithm:62:0, 
       from main.cpp:2: 
/usr/local/include/c++/5.3.0/bits/stl_algo.h: In instantiation of 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::_List_iterator<int>; _Compare = __gnu_cxx::__ops::_Iter_less_iter]': 
/usr/local/include/c++/5.3.0/bits/stl_algo.h:4698:18: required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]' 
main.cpp:6:14: required from 'void sort_no_sfinae(C&) [with C = std::__cxx11::list<int>]' 
main.cpp:11:21: required from here 
/usr/local/include/c++/5.3.0/bits/stl_algo.h:1964:22: error: no match for 'operator-' (operand types are 'std::_List_iterator<int>' and 'std::_List_iterator<int>') 
    std::__lg(__last - __first) * 2, 
        ^
In file included from /usr/local/include/c++/5.3.0/bits/stl_algobase.h:67:0, 
       from /usr/local/include/c++/5.3.0/list:60, 
       from main.cpp:1: 
/usr/local/include/c++/5.3.0/bits/stl_iterator.h:328:5: note: candidate: template<class _Iterator> typename std::reverse_iterator<_Iterator>::difference_type std::operator-(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&) 
    operator-(const reverse_iterator<_Iterator>& __x, 
    ^
/usr/local/include/c++/5.3.0/bits/stl_iterator.h:328:5: note: template argument deduction/substitution failed: 
In file included from /usr/local/include/c++/5.3.0/algorithm:62:0, 
       from main.cpp:2: 
/usr/local/include/c++/5.3.0/bits/stl_algo.h:1964:22: note: 'std::_List_iterator<int>' is not derived from 'const std::reverse_iterator<_Iterator>' 
    std::__lg(__last - __first) * 2, 
        ^
In file included from /usr/local/include/c++/5.3.0/bits/stl_algobase.h:67:0, 
       from /usr/local/include/c++/5.3.0/list:60, 
       from main.cpp:1: 
/usr/local/include/c++/5.3.0/bits/stl_iterator.h:380:5: note: candidate: template<class _IteratorL, class _IteratorR> decltype ((__y.base() - __x.base())) std::operator-(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_IteratorR>&) 
    operator-(const reverse_iterator<_IteratorL>& __x, 
    ^
/usr/local/include/c++/5.3.0/bits/stl_iterator.h:380:5: note: template argument deduction/substitution failed: 
In file included from /usr/local/include/c++/5.3.0/algorithm:62:0, 
       from main.cpp:2: 
/usr/local/include/c++/5.3.0/bits/stl_algo.h:1964:22: note: 'std::_List_iterator<int>' is not derived from 'const std::reverse_iterator<_Iterator>' 
    std::__lg(__last - __first) * 2, 
        ^
In file included from /usr/local/include/c++/5.3.0/bits/stl_algobase.h:67:0, 
       from /usr/local/include/c++/5.3.0/list:60, 
       from main.cpp:1: 
/usr/local/include/c++/5.3.0/bits/stl_iterator.h:1138:5: note: candidate: template<class _IteratorL, class _IteratorR> decltype ((__x.base() - __y.base())) std::operator-(const std::move_iterator<_Iterator>&, const std::move_iterator<_IteratorR>&) 
    operator-(const move_iterator<_IteratorL>& __x, 
    ^
/usr/local/include/c++/5.3.0/bits/stl_iterator.h:1138:5: note: template argument deduction/substitution failed: 
In file included from /usr/local/include/c++/5.3.0/algorithm:62:0, 
       from main.cpp:2: 
/usr/local/include/c++/5.3.0/bits/stl_algo.h:1964:22: note: 'std::_List_iterator<int>' is not derived from 'const std::move_iterator<_Iterator>' 
    std::__lg(__last - __first) * 2, 
        ^
In file included from /usr/local/include/c++/5.3.0/bits/stl_algobase.h:67:0, 
       from /usr/local/include/c++/5.3.0/list:60, 
       from main.cpp:1: 
/usr/local/include/c++/5.3.0/bits/stl_iterator.h:1145:5: note: candidate: template<class _Iterator> decltype ((__x.base() - __y.base())) std::operator-(const std::move_iterator<_Iterator>&, const std::move_iterator<_Iterator>&) 
    operator-(const move_iterator<_Iterator>& __x, 
    ^
/usr/local/include/c++/5.3.0/bits/stl_iterator.h:1145:5: note: template argument deduction/substitution failed: 
In file included from /usr/local/include/c++/5.3.0/algorithm:62:0, 
       from main.cpp:2: 
/usr/local/include/c++/5.3.0/bits/stl_algo.h:1964:22: note: 'std::_List_iterator<int>' is not derived from 'const std::move_iterator<_Iterator>' 
    std::__lg(__last - __first) * 2, 
        ^
In file included from /usr/local/include/c++/5.3.0/vector:65:0, 
       from /usr/local/include/c++/5.3.0/bits/random.h:34, 
       from /usr/local/include/c++/5.3.0/random:49, 
       from /usr/local/include/c++/5.3.0/bits/stl_algo.h:66, 
       from /usr/local/include/c++/5.3.0/algorithm:62, 
       from main.cpp:2: 
/usr/local/include/c++/5.3.0/bits/stl_bvector.h:208:3: note: candidate: std::ptrdiff_t std::operator-(const std::_Bit_iterator_base&, const std::_Bit_iterator_base&) 
    operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) 
^
/usr/local/include/c++/5.3.0/bits/stl_bvector.h:208:3: note: no known conversion for argument 1 from 'std::_List_iterator<int>' to 'const std::_Bit_iterator_base&' 
+0

取点。如果概念实施了,它们会是多余的吗? – experquisite

+0

@experquisite SFINAE基本上是我们可以做的最好的黑客版本的概念。有了概念,错误会是[*甚至更好](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3701.pdf)。 – Barry

+1

@Barry这取决于。如果我有二十多个重载,也许我更喜欢从我感兴趣的重载的内容中发现一个错误,而不是二十多个主要关于我不在乎的重载的消息。 –

相关问题