// Copyright (c) 2003 Utrecht University (The Netherlands), // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany), // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; version 2.1 of the License. // See the file LICENSE.LGPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $Source$ // $Revision$ $Date$ // $Name$ // // Author(s) : Sylvain Pion // --------------------------------------------------------------------- // A short test program to evaluate a C++ compiler. // This program is used by cgal_configure. // The following documentation will be pasted in the generated configfile. // --------------------------------------------------------------------- //| This flag is set if the compiler doesn't support the SFINAE principle //| (Substitution Failure Is Not An Error), which we eventually plan to use //| for the next version of the kernel design. class My_vector { // 2D vector type int _x, _y; public: My_vector(int x, int y) : _x(x), _y(y) {} int x() const { return _x; } int y() const { return _y; } }; class My_point { // 2D point type int _x, _y; public: typedef My_vector Vector_2; // type returned by p-q; My_point(int x, int y) : _x(x), _y(y) {} int x() const { return _x; } int y() const { return _y; } }; // Traits class determining if a type is a 2D vector. template < typename > struct IsVector_2 { enum { value = false }; }; template <> struct IsVector_2 { enum { value = true }; }; // Traits class determining if a type is a 2D point. template < typename > struct IsPoint_2 { enum { value = false }; }; template <> struct IsPoint_2 { enum { value = true }; }; // Enable_if : tool for SFINAE template < bool, typename > struct Enable_if {}; template < typename T > struct Enable_if { typedef T type; }; // Workaround for making the following signature slightly different // on the arguments (otherwise g++ 3.2 barfs on it). template < typename T > struct Same { typedef T type; }; #define SAME(T) typename Same::type // #define SAME(T) T template < typename Vector_2 > typename Enable_if< IsVector_2::value, Vector_2 >::type operator-(Vector_2 const &v, Vector_2 const &w) { return Vector_2(v.x() - w.x(), v.y() - w.y()); } template < typename Vector_2 > typename Enable_if< IsVector_2::value, Vector_2 >::type operator+(Vector_2 const &v, Vector_2 const &w) { return Vector_2(v.x() + w.x(), v.y() + w.y()); } template < typename Point_2 > typename Enable_if< IsPoint_2::value, Point_2 >::type::Vector_2 operator-(Point_2 const &p, SAME(Point_2) const &q) { typedef typename Point_2::Vector_2 Vector_2; return Vector_2(p.x() - q.x(), p.y() - q.y()); } int main() { My_vector v(1,2), w(3,4); My_vector z = v - w; // OK My_vector y = v + w; // OK My_point p(1,2), q(3,4); My_vector r = p - q; // OK // My_point s = p + q; // error : // no match for `My_point& + My_point&' operator (void) z; (void) y; (void) r; return 0; }