From 051bde253653b9e44bdd81baf54c93f6922645e0 Mon Sep 17 00:00:00 2001 From: wolf Date: Fri, 14 Feb 2003 22:46:52 +0000 Subject: [PATCH] Add SFINAE check. git-svn-id: https://svn.dealii.org/trunk@7095 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/aclocal.m4 | 84 +++++++++++++++++++++++++++ deal.II/base/include/base/config.h.in | 5 ++ deal.II/configure | 83 +++++++++++++++++++++++++- deal.II/configure.in | 1 + 4 files changed, 172 insertions(+), 1 deletion(-) diff --git a/deal.II/aclocal.m4 b/deal.II/aclocal.m4 index 37b378a1b7..2d26bc16cb 100644 --- a/deal.II/aclocal.m4 +++ b/deal.II/aclocal.m4 @@ -2400,6 +2400,90 @@ AC_DEFUN(DEAL_II_CHECK_LONG_DOUBLE_LOOP_BUG, dnl +dnl ------------------------------------------------------------- +dnl We have so many templates in deal.II that sometimes we need +dnl to make it clear with which types a template parameter can +dnl be instantiated. There is a neat trick to do this: SFINAE +dnl (substitution failure is not an error). The idea is this: the +dnl C++ standard prescribes that a template function is only +dnl considered in a call, if all parts of its signature can be +dnl instantiated with the template parameter replaced by the +dnl respective types/values in this particular call. Example: +dnl template +dnl typename T::type foo(T) {...}; +dnl ... +dnl foo(1); +dnl +dnl The compiler should detect that in this call, the template +dnl parameter T must be identified with the type "int". However, +dnl the return type T::type does not exist. The trick now is +dnl that this is not considered an error: this template is simply +dnl not considered, the compiler keeps on looking for another +dnl possible function foo. +dnl +dnl That allows for a neat trick to rule out a template for certain +dnl template arguments without changing the function signature at +dnl all: Make the return type un-instantiable if the template +dnl type presently considered for instantiation does not qualify. +dnl An example of this is shown below. +dnl +dnl Unfortunately, older compilers do not support this trick: they +dnl issue an error if the return type cannot be installed. In this +dnl case, we back out and just drop the constraint and allow for +dnl all template types. In that case, you'll simply get compiler +dnl error when it tries to compile this template (in case it's in +dnl the .h file), or linker errors for missing functions in case +dnl it's in the .cc file and explicitly instantiated. +dnl +dnl Usage: DEAL_II_CHECK_SFINAE_BUG +dnl +dnl ------------------------------------------------------------- +AC_DEFUN(DEAL_II_CHECK_SFINAE_BUG, dnl +[ + AC_MSG_CHECKING(for SFINAE bug) + AC_LANG(C++) + CXXFLAGS="$CXXFLAGSG" + AC_TRY_COMPILE( + [ + template struct int_or_double { static const bool value = false;}; + template <> struct int_or_double { static const bool value = true; }; + template <> struct int_or_double { static const bool value = true; }; + + template struct constraint_and_return_value {}; + + template struct constraint_and_return_value + { + typedef T type; + }; + + // deduction for T=char should file, since return type cannot be + // instantiated... + template + typename constraint_and_return_value::value,void>::type + f (T); + + // ...however, this is not an error. rather, the compiler should + // instead choose the following function: + void f(int); + ], + [ + f('c'); + ], + [ + AC_MSG_RESULT(no) + ], + [ + AC_MSG_RESULT(yes. disabling template constraints) + AC_DEFINE(DEAL_II_SFINAE_BUG, 1, + [Defined if the compiler does not support the + substitution-failure-is-not-an-error paradigm. + For the details, look at aclocal.m4 in the + top-level directory.]) + ]) +]) + + + dnl ------------------------------------------------------------- dnl The boost::shared_ptr class has a templated assignment operator diff --git a/deal.II/base/include/base/config.h.in b/deal.II/base/include/base/config.h.in index 5402fdd106..8773576b76 100644 --- a/deal.II/base/include/base/config.h.in +++ b/deal.II/base/include/base/config.h.in @@ -96,6 +96,11 @@ /* Path to the deal.II directory */ #undef DEAL_II_PATH +/* Defined if the compiler does not support the + substitution-failure-is-not-an-error paradigm. For the details, look at + aclocal.m4 in the top-level directory. */ +#undef DEAL_II_SFINAE_BUG + /* Define if we have to work around a bug in Sun's Forte compiler. See the aclocal.m4 file in the top-level directory for a description of this bug. */ diff --git a/deal.II/configure b/deal.II/configure index 66fa4cb198..c88e438aaf 100755 --- a/deal.II/configure +++ b/deal.II/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 1.141.2.1 . +# From configure.in Revision: 1.142 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.57. # @@ -4966,6 +4966,87 @@ cat >>confdefs.h <<\_ACEOF _ACEOF +fi +rm -f conftest.$ac_objext conftest.$ac_ext + + + echo "$as_me:$LINENO: checking for SFINAE bug" >&5 +echo $ECHO_N "checking for SFINAE bug... $ECHO_C" >&6 + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CXXFLAGS="$CXXFLAGSG" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + template struct int_or_double { static const bool value = false;}; + template <> struct int_or_double { static const bool value = true; }; + template <> struct int_or_double { static const bool value = true; }; + + template struct constraint_and_return_value {}; + + template struct constraint_and_return_value + { + typedef T type; + }; + + // deduction for T=char should file, since return type cannot be + // instantiated... + template + typename constraint_and_return_value::value,void>::type + f (T); + + // ...however, this is not an error. rather, the compiler should + // instead choose the following function: + void f(int); + +int +main () +{ + + f('c'); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + echo "$as_me:$LINENO: result: yes. disabling template constraints" >&5 +echo "${ECHO_T}yes. disabling template constraints" >&6 + +cat >>confdefs.h <<\_ACEOF +#define DEAL_II_SFINAE_BUG 1 +_ACEOF + + fi rm -f conftest.$ac_objext conftest.$ac_ext diff --git a/deal.II/configure.in b/deal.II/configure.in index 1593df5c55..9d72ce61b3 100644 --- a/deal.II/configure.in +++ b/deal.II/configure.in @@ -176,6 +176,7 @@ DEAL_II_CHECK_TEMPLATE_TEMPLATE_TYPEDEF_BUG DEAL_II_CHECK_NESTED_CLASS_FRIEND_BUG DEAL_II_CHECK_MEMBER_VAR_SPECIALIZATION_BUG DEAL_II_CHECK_LONG_DOUBLE_LOOP_BUG +DEAL_II_CHECK_SFINAE_BUG DEAL_II_CHECK_BOOST_SHARED_PTR_ASSIGNMENT DEAL_II_HAVE_PRETTY_FUNCTION DEAL_II_HAVE_STD_ITERATOR -- 2.39.5