<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jul 29, 2015 at 2:02 PM, Pete Cooper <span dir="ltr"><<a href="mailto:peter_cooper@apple.com" target="_blank">peter_cooper@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On Jul 29, 2015, at 1:50 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:</div><br><div><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">Yep, something like that looks about right. I'm not sure if it can be generalized further so we can reuse some of the machinery for begin, end, rbegin, rend, getDecl, etc. You can probably just SFINAE on begin/rbegin and assume end/rend exist - but if we can get the SFINAE tidy enough it wouldn't hurt to test for both, I suppose.</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">btw, my change to the test that demonstrates the problem with using universal ref/lvalue ref distinction to differentiate is this: add "const ReverseOnlyVector/const BidirectionalVector" to the Types vector & you'll see failures in the existing implementation. Alternatively/in addition, could refactor out the body of the TrivialOperation test into a template, then instantiate that template with TypeParam and const TypeParam, so you don't have to list all of them as const/non-const in the list of types.</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">Also, I added this rvalue version:</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">template <typename T> struct RangeAdapterRValueTest : testing::Test {};</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">typedef ::testing::Types<std::vector<int>, std::list<int>, ReverseOnlyVector,</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">                         BidirectionalVector> RangeAdapterRValueTestTypes;</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">TYPED_TEST_CASE(RangeAdapterRValueTest, RangeAdapterRValueTestTypes);</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">template<typename R></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">void TestRev(const R& r) {</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">  int counter = 3;</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">  for (int i : r)</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">    EXPECT_EQ(i, counter--);</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">}</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">TYPED_TEST(RangeAdapterRValueTest, TrivialOperation) {</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">  TestRev(reverse(TypeParam({0, 1, 2, 3})));</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">}</div></div></blockquote></span>Very nice.  Thanks for doing that.</div><div><br></div><div>Here’s a patch with the fixes.  I had to extend has_rbegin to handle whether its a class or not (int[] failed without that).  Otherwise its basically just like has_getDecl.  I think has_getDecl is in an internal namespace.  I can do the same here if you like, i’m fine either way.</div></div></blockquote><div><br>So the rvalue tests I added don't cover the non-rvalue case your existing test cases covered (nor the array cases) - looks like you dropped the originals?<br><br>I wonder if the SFINAE can be done without trying to derive from the type (some types might not be derivable)<br><br>Maybe the hasDecl was written pre-C++11?<br><br>This /seems/ to work in the basic case:<br><br><div>struct foo {</div><div>  void func();</div><div>};</div><div><br></div><div>struct bar {</div><div>};</div><div><br></div><div>template<typename T></div><div>struct has_func {</div><div>  template<typename U></div><div>  static char (&f(const U&, decltype(&U::func)))[1];</div><div>  static char (&f(...))[2];</div><div>  const static bool value = sizeof(f(std::declval<T>(), nullptr)) == 1;</div><div>};</div><div><br></div><div>static_assert(has_func<foo>::value, "");</div><div>static_assert(!has_func<bar>::value, "");<br><br>(plus the extra non-class detection you had too)</div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><br></div><div>Cheers,</div><div>Pete</div><div><br></div><div><br></div></div><br><div style="word-wrap:break-word"></div><br></blockquote></div><br></div></div>