On 22 August 2012 21:37, Jonathan Wakely <jwakely.gcc@xxxxxxxxx> wrote: > On 22 August 2012 19:49, Onay Urfalioglu wrote: >> The following code compiles fine with g++-4.7.1 in c++11 mode, but I think >> it should give errors for the last source line "auto res2 = 2 * >> std::list<int>();" (SFINAE ?) > > I don't think it should. > >> // compile cmd: >> // g++ c++11-test.cpp -o cpp11-test -std=c++11 >> >> #include <vector> >> #include <list> >> >> template<typename T> >> struct HasRandomAccessOp { >> HasRandomAccessOp(const T &v) { >> typedef decltype(v[0]) test_type; > > This type is only used in the body of the constructor. That means the > constructor must be instantiated for the error to be detected. > >> } >> }; >> >> template<typename T, typename T_VECTOR> >> int operator*(const T &l, const T_VECTOR &r) { >> typedef decltype(HasRandomAccessOp<T_VECTOR>(r)) >> random_access_test_type; > > The constructor doesn't need to be instantiated for decltype to know > the type of that expression, the type is obviously > HasRandomAccessOp<T_VECTOR>. > > Even if the constructor was instantiated, SFINAE would not apply, > because the error happens in the function body, not in the context > where template argument deduction takes place, i.e. in determining the > function signature by substituting the template arguments for the > function parameter types and return type. > >> return 1; >> } >> >> int main() { >> std::vector<int> iv = {1,2}; >> >> auto res1 = 1 * iv; >> auto res2 = 2 * std::list<int>(); >> } You could do something like this instead: template<typename T> struct HasRandomAccessOp { typedef decltype(std::declval<T>()[0]) test_type; }; template<typename T, typename T_VECTOR, typename = typename HasRandomAccessOp<T_VECTOR>::test_type> int operator*(const T &l, const T_VECTOR &r) { return 1; } Now the invalid type occurs in a context where SFINAE applies, so the function is removed from the overload set for types without a suitable operator[].