The following code comes from cxx-prettyprint , which implements detecting whether type T has a corresponding member
#include<iostream>
#include<vector>
#include<type_traits>
using namespace std;
struct sfinae_base
{
using yes = char;
using no = yes[2];
};
template <typename T>
struct has_const_iterator : private sfinae_base
{
private:
template <typename C> static yes& test(typename C::const_iterator*);
template <typename C> static no& test(...);
public:
static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
using type = T;
};
template <typename T>
struct has_begin_end : private sfinae_base
{
private:
template <typename C>
static yes& f(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::begin)),
typename C::const_iterator(C::*)() const>::value>::type*);
template <typename C> static no& f(...);
template <typename C>
static yes& g(typename std::enable_if<
std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::end)),
typename C::const_iterator(C::*)() const>::value, void>::type*);
template <typename C> static no& g(...);
public:
static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
};
int main()
{
vector<int> sa{ 1,2,3,4,5 };
cout << has_const_iterator<vector<int>>::value;
cout<<has_begin_end<vector<int>>::beg_value;
cout << has_begin_end<vector<int>>::end_value;
return 0;
}
Some time later I read someone else's blog and changed it to this
#include<utility>
#include<iostream>
#include<vector>
using namespace std;
template <typename T>
struct has_const_iterator
{
private:
template <typename U>
static constexpr decltype(std::declval<U::const_iterator>(), bool()) test(int) { return true; }
template <typename U>
static constexpr bool test(...) { return false; }
public:
static const bool value = test<T>(1); //为什么这个不对?
using type = T;
};
template <typename T>
struct has_begin_end
{
private:
template <typename U>
static constexpr decltype(std::declval<U>().begin(), bool()) f(int) { return true; }
template <typename U>
static constexpr bool f(...) { return false; }
template <typename U>
static constexpr decltype(std::declval<U>().end(), bool()) g(int) { return true; }
template <typename U>
static constexpr bool g(...) { return false; }
public:
static bool const beg_value = f<T>(2);
static bool const end_value = g<T>(2);
};
int main()
{
vector<int> sa{ 1,2,3,4,5 };
cout << has_const_iterator<vector<int>>::value;
cout<<has_begin_end<vector<int>>::beg_value;
cout << has_begin_end<vector<int>>::end_value;
return 0;
}
For the first piece of code it shows 111
For the second piece of code it shows 011
Snippet 2 was working fine a few months ago, but not now.
My question is, what's wrong with the second one,and why it was good before and now goes wrong?
Added: I found this, what does he mean by introduce ODR violations
?