text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    TestCxxFeatures.cxx
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  
       This software is distributed WITHOUT ANY WARRANTY; without even
       the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE.  See the above copyright notice for more information.
  
  =========================================================================*/
  
  // .NAME TestCxxFeatures
  // .SECTION Description
  // Provides a reference for the set of C++ features that can be used
  // by VTK.
  
  #include "vtkConfigure.h"
  
  //----------------------------------------------------------------------------
  
  /* Check for known compilers.  */
  
  #if defined(__HP_aCC)
  # define VTK_CXX_ACC
  #endif
  
  #if defined(__SUNPRO_CC)
  # define VTK_CXX_SUNPRO
  #endif
  
  //----------------------------------------------------------------------------
  
  /* Check for known compiler limitations.  */
  
  // Assume standard behavior if symbol is not already defined.
  #if !defined(VTK_TYPENAME)
  # define VTK_TYPENAME typename
  #endif
  
  // Assume standard behavior if symbol is not already defined.
  #if !defined(VTK_CLASS_TEMPLATE_SPECIALIZATION)
  # define VTK_CLASS_TEMPLATE_SPECIALIZATION template <>
  #endif
  
  //----------------------------------------------------------------------------
  
  #include "vtkSystemIncludes.h"
  
  //----------------------------------------------------------------------------
  
  /* Test inclusion of typeinfo header.  */
  
  #include <typeinfo>
  
  //----------------------------------------------------------------------------
  
  /* Test nested classes defined outside.  */
  
  class NestedTestOuter
  {
  public:
    NestedTestOuter();
    ~NestedTestOuter();
  private:
    class NestedTestInner;
    NestedTestInner* Inner;
  };
  
  class NestedTestOuter::NestedTestInner
  {
  public:
    NestedTestInner() {}
    ~NestedTestInner() {}
  };
  
  NestedTestOuter::NestedTestOuter()
  {
    this->Inner = new NestedTestInner;
  }
  
  NestedTestOuter::~NestedTestOuter()
  {
    delete this->Inner;
  }
  
  //----------------------------------------------------------------------------
  
  /* Test inclusion of some stl headers.  */
  #ifdef _MSC_VER
  #pragma warning (push, 2)
  #endif
  
  #include <vector>
  
  #ifdef _MSC_VER
  #pragma warning(pop)
  #endif
  
  //----------------------------------------------------------------------------
  
  /* Test full template specialization of functions.  */
  template <class T>
  int FullySpecializedFunction(T*)
  {
    return 0;
  }
  
  template <>
  int FullySpecializedFunction<int>(int*)
  {
    return 1;
  }
  
  int TestFullySpecializedFunction()
  {
    int result = 1;
    int should_be_0 = FullySpecializedFunction(static_cast<float*>(0));
    if(should_be_0 != 0)
    {
      cerr << "FullySpecializedFunction<float*>() returned "
           << should_be_0 << ", not 0.\n";
      result = 0;
    }
    int should_be_1 = FullySpecializedFunction(static_cast<int*>(0));
    if(should_be_1 != 1)
    {
      cerr << "FullySpecializedFunction(int*) returned "
           << should_be_1 << ", not 1.\n";
      result = 0;
    }
    return result;
  }
  
  //----------------------------------------------------------------------------
  
  /* Test member template of non-template.  */
  
  class NonTemplate
  {
    void* Pointer;
  public:
    template <class T> void Set(T* t) { this->Pointer = t; }
    template <class T> void Get(T*& t) { t = static_cast<T*>(this->Pointer); }
  };
  
  int TestNonTemplateMemberTemplate()
  {
    int x = 123;
    int* px = 0;
    NonTemplate nt;
    nt.Set(&x);
    nt.Get(px);
    return (*px == 123);
  }
  
  //----------------------------------------------------------------------------
  
  /* Test member template of template.  */
  
  template <class T>
  class OuterTemplate
  {
    T* Pointer;
  public:
    template <class U> void Set(U* u) { this->Pointer = u; }
    template <class U> void Get(U*& u) { u = static_cast<U*>(this->Pointer); }
  };
  
  int TestTemplateMemberTemplate()
  {
    int x = 123;
    int* px = 0;
    OuterTemplate<void> nt;
    nt.Set(&x);
    nt.Get(px);
    return (*px == 123);
  }
  
  //----------------------------------------------------------------------------
  
  /* Test full template specialization of classes.  */
  
  template <class T>
  struct FullySpecializedClass
  {
    static int Method() { return 0; }
    typedef T Type;
  };
  
  VTK_CLASS_TEMPLATE_SPECIALIZATION
  struct FullySpecializedClass<float>
  {
    static int Method() { return 1; }
    typedef int Type;
  };
  
  template <class T>
  int TestFullySpecializedClassTrait(T*)
  {
    typedef VTK_TYPENAME FullySpecializedClass<T>::Type Type;
    if(static_cast<Type>(3.1) == 3.1)
    {
      return 0;
    }
    return 1;
  }
  
  int TestFullySpecializedClass()
  {
    int result = 1;
    int should_be_0 = FullySpecializedClass<int>::Method();
    if(should_be_0 != 0)
    {
      cerr << "FullySpecializedClass<int>::Method() returned "
           << should_be_0 << ", not 0.\n";
      result = 0;
    }
    int should_be_1 = FullySpecializedClass<float>::Method();
    if(should_be_1 != 1)
    {
      cerr << "FullySpecializedClass<float>::Method() returned "
           << should_be_1 << ", not 1.\n";
      result = 0;
    }
    if(!TestFullySpecializedClassTrait(static_cast<float*>(0)))
    {
      cerr << "Trait lookup of float didn't produce int.";
      result = 0;
    }
    return result;
  }
  
  //----------------------------------------------------------------------------
  
  /* Test if(int x = f()) style scoping.  */
  
  int TestIfScopeHelper(int i)
  {
    int result = 1;
    if(int x = i)
    {
      if(x != i)
      {
        cerr << "TestIfScope: x != " << i << "\n";
        result = 0;
      }
    }
    else
    {
      if(x != i)
      {
        cerr << "TestIfScope: x != " << i << "\n";
        result = 0;
      }
    }
    int x = result;
    return x;
  }
  
  int TestIfScope()
  {
    int result = 1;
    if(!TestIfScopeHelper(1))
    {
      result = 0;
    }
    if(!TestIfScopeHelper(0))
    {
      result = 0;
    }
    return result;
  }
  
  //----------------------------------------------------------------------------
  
  /* Test non-type template parameter.  */
  
  template <int I>
  struct NonTypeTemplate
  {
    static int GetValue() { return I; }
  };
  
  int TestNonTypeTemplate()
  {
    int result = 1;
    if(NonTypeTemplate<0>::GetValue() != 0)
    {
      cerr << "NonTypeTemplate<0>::GetValue() != 0\n";
      result = 0;
    }
    if(NonTypeTemplate<1>::GetValue() != 1)
    {
      cerr << "NonTypeTemplate<1>::GetValue() != 1\n";
      result = 0;
    }
    if(NonTypeTemplate<2>::GetValue() != 2)
    {
      cerr << "NonTypeTemplate<2>::GetValue() != 2\n";
      result = 0;
    }
    return result;
  }
  
  //----------------------------------------------------------------------------
  
  /* Test mixed type and non-type template arguments in a non-trival way.  */
  
  #if !defined(__BORLANDC__)
  // Borland does not support this fancy array template.
  template <class T, int N>
  int TestMixedTypeTemplateFunction(T (*)[N])
  {
    return N;
  }
  int TestMixedTypeTemplate()
  {
    int x2[2];
    float x3[3];
    int result = 1;
    if(TestMixedTypeTemplateFunction(&x2) != 2)
    {
      cerr << "TestMixedTypeTemplateFunction(&x2) != 2\n";
      result = 0;
    }
    if(TestMixedTypeTemplateFunction(&x3) != 3)
    {
      cerr << "TestMixedTypeTemplateFunction(&x3) != 3\n";
      result = 0;
    }
    return result;
  }
  #endif
  
  //----------------------------------------------------------------------------
  
  class SafeBoolIdiomClass
  {
  private:
    struct SafeBoolDummy { void Dummy() {} };
    typedef void (SafeBoolDummy::* SafeBool)();
  public:
    SafeBoolIdiomClass(int x): Value(x) {}
    operator SafeBool()
    {
      return this->Value? &SafeBoolDummy::Dummy : 0;
    }
    SafeBool operator !()
    {
      return this->Value? 0 : &SafeBoolDummy::Dummy;
    }
  protected:
    int Value;
  };
  
  int TestSafeBoolIdiom()
  {
    int result = 1;
    SafeBoolIdiomClass cTrue(1);
    SafeBoolIdiomClass cFalse(0);
    if(cTrue) {}
    else
    {
      cerr << "if(cTrue) evaluates to false.\n";
      result = 0;
    }
    if(!cTrue)
    {
      cerr << "if(!cTrue) evaluates to true.\n";
      result = 0;
    }
    if(cFalse)
    {
      cerr << "if(cFalse) evaluates to true.\n";
      result = 0;
    }
    if(!cFalse) {}
    else
    {
      cerr << "if(!cFalse) evaluates to false.\n";
      result = 0;
    }
    return result;
  }
  
  //----------------------------------------------------------------------------
  
  /* Test use of exceptions.  */
  
  #if defined(_MSC_VER)
  # pragma warning (push)
  # pragma warning (disable: 4702) /* Unreachable code. */
  #endif
  
  class TestExceptionUnwind
  {
    int* pvalue;
  public:
    TestExceptionUnwind(int* p): pvalue(p) {}
    ~TestExceptionUnwind() { *pvalue = 1; }
    void Use() {}
  };
  
  class ExceptionClass {};
  
  void TestThrowException(int* p)
  {
    TestExceptionUnwind unwind(p);
    unwind.Use();
    throw ExceptionClass();
  }
  
  int TestException()
  {
    int value = 0;
    try
    {
      TestThrowException(&value);
    }
    catch(ExceptionClass&)
    {
      if(value)
      {
        return 1;
      }
      else
      {
        cerr << "TestExceptionUnwind object not destroyed!" << endl;
        return 0;
      }
    }
    catch(...)
    {
      cerr << "ExceptionClass not caught!" << endl;
      return 0;
    }
    cerr << "No exception caught!" << endl;
    return 0;
  }
  
  #if defined(_MSC_VER)
  # pragma warning (pop)
  #endif
  
  //----------------------------------------------------------------------------
  
  /* Test void return type syntax.  */
  
  // Intel C++ warns about type qualifiers on return types.
  #if defined(__INTEL_COMPILER)
  # pragma warning (push)
  # pragma warning (disable:858) // type qualifier on return is meaningless
  #endif
  
  // clang warns about type qualifiers on return types.
  #if defined(__clang__)
  # pragma clang diagnostic push
  # pragma clang diagnostic ignored "-Wignored-qualifiers"
  #endif
  
  // gcc>=4.3 says type qualifiers ignored on function return type
  #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)))
  # pragma GCC diagnostic push
  #endif
  #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)))
  # pragma GCC diagnostic ignored "-Wignored-qualifiers"
  #endif
  
  // aCC warns "type qualifier on return type is meaningless" - just omit the
  // function on aCC builds since there is no way to suppress the warning via
  // pragmas...
  #if !defined(__HP_aCC)
  void const TestVoidConstReturn() {}
  #endif
  
  #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)))
  # pragma GCC diagnostic pop
  #endif
  
  #if defined(__clang__)
  # pragma clang diagnostic pop
  #endif
  
  #if defined(__INTEL_COMPILER)
  # pragma warning (pop)
  #endif
  
  //-------------------------------------------------------------------
  // See if the following code works on all platforms
  #if defined(_MSC_VER) && defined(_DEBUG)
  /* MSVC debug hook to prevent dialogs when running from DART.  */
  # include <crtdbg.h>
  static int TestDriverDebugReport(int type, char* message, int* retVal)
  {
    (void)type; (void)retVal;
    fprintf(stderr, message);
    exit(1);
  }
  #endif
  
  
  //----------------------------------------------------------------------------
  
  /* Test setlocale  */
  #include <locale.h>
  int TestSetLocale()
  {
    char *oldLocale = strdup(setlocale(LC_NUMERIC,NULL));
    setlocale(LC_NUMERIC,"English");
  
    // restore the local
    if (oldLocale)
    {
      setlocale(LC_NUMERIC,oldLocale);
      free(oldLocale);
      return 1;
    }
    return 0;
  }
  
  //----------------------------------------------------------------------------
  
  #define DO_TEST(x) \
    if(x()) { cout << "Passed: " #x "\n"; } \
    else { cout << "Failed: " #x "\n"; result = 1; }
  
  int main()
  {
    int result = 0;
    DO_TEST(TestFullySpecializedFunction);
    DO_TEST(TestNonTemplateMemberTemplate);
    DO_TEST(TestTemplateMemberTemplate);
    DO_TEST(TestFullySpecializedClass);
    DO_TEST(TestIfScope);
    DO_TEST(TestNonTypeTemplate);
  #if !defined(__BORLANDC__)
    DO_TEST(TestMixedTypeTemplate);
  #endif
    DO_TEST(TestSafeBoolIdiom);
    DO_TEST(TestException);
    DO_TEST(TestSetLocale);
  
  #if defined(_MSC_VER) && defined(_DEBUG)
    // just call the code to shut up a linker warning
    int retVal = 0;
    if (result)
    {
      // really shouldn't be called unless something else failed
      // just want to make the compiler think it might get called
      // all this will be yanked once I see the results of this test
      TestDriverDebugReport(0, "a temp test", &retVal);
    }
  #endif
    return result;
  }
  