Ok.
Your
fast_sort compiles for types which
a. have no more than one overload of begin, end, or sort, and
b. have either a begin-end pair or sort, not both.
So types like
std::vector<T> and
std::list<T> are excluded, but a contrived type like
struct has_sort { void sort() {}; };
Is acceptable. This is what I tried to fix in the code I posted.
I don't know why MSVC won't compile your program. It looks like a compiler bug to me. However, given the error message, I find it possible that the program is ill-formed NDR and only MSVC is emitting a diagnostic.
So we need to have differing signatures for each fast_sort, right? |
A function template's return type is part of its signature. [defns.signature.templ]
http://eel.is/c++draft/defns.signature.templ
Whether the code is well-formed seems to depend on [temp.over.link] or the ODR. Maybe MSVC's traditionally incorrect name lookup is involved too.
http://eel.is/c++draft/temp.over.link
It appears that you can sidestep the problem by comparing the sizes inside a class template as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
#include <iostream>
#include <type_traits>
#include <utility>
#include <algorithm>
struct has_sort { void sort() {}; };
struct has_range { void begin() {}; void end() {}; };
struct have_sort { char c; };
struct have_range { char c; have_sort c2; };
struct have_nothing { char c; have_range c2; };
template<typename T> have_sort test_sort(decltype(&T::sort), decltype(&T::sort));
template<typename T> have_range test_sort(decltype(&T::begin), decltype(&T::end));
template<typename T> have_nothing test_sort(...);
template <std::size_t I, std::size_t J> struct eq { static constexpr bool value = (I == J); };
template<typename T>
typename std::enable_if<eq<sizeof(test_sort<T>(nullptr, nullptr)), sizeof(have_sort)>::value>::type fast_sort(T&)
{
}
template<typename T>
typename std::enable_if<eq<sizeof(test_sort<T>(nullptr, nullptr)), sizeof(have_range)>::value>::type fast_sort(T&)
{
//std::sort(x.begin(), x.end());
}
int main()
{
has_sort x;
has_range y;
fast_sort(x);
fast_sort(y);
}
| |
Which compiles under my version of cl.exe, although I'd not use this code without knowing for certain whether it is correct under Microsoft's toolchain.
D:\>cl /?
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29111 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ] |
It could also be something dumb that I have forgotten. That's always a possibility.