Intel® C++ Compiler
Support and discussions for creating C++ code that runs on platforms based on Intel® processors.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!
7568 Discussions

bug with explicit template parameter on member function / decltype / type name is not allowed

Ingo_L_
Beginner
212 Views

While compiling code, that should check for the existance of a template member function with explicit parameter, compiler fails with

error: type name is not allowed
      template <typename _1> static true_t Test(_1* p, decltype(p->StaticInterfaceCast<interfaceT>())* = nullptr);

problem is unrelated to decltype but to explicit template parameters on member functions. On vs2012 code compiles.

This is the test mpl compatible predicate

  template <typename T, typename interfaceT>  struct HasStaticInterfaceCast
  {
    typedef char true_t[1];
    typedef char false_t[2];
    template <typename _1> static false_t Test(...);
    template <typename _1> static true_t Test(_1* p, decltype(p->StaticInterfaceCast<interfaceT>())* = nullptr);
    static value_type const value = sizeof(Test<T>((T*)0)) == sizeof(true_t);
  };

And the test code --- ofc, cannot be executed, because compilation of predicate fails


  struct Interface;
  struct Tester
  {
    template <typename T> boost::enable_if<boost::is_same<T,Interface>,T>::type* StaticInterfaceCast() const;
  };

  BOOST_MPL_ASSERT((HasStaticInterfaceCast<Tester,Interface>));

Is there any know workaround ? Because it keeps me from migrating the source code.

0 Kudos
3 Replies
Judith_W_Intel
Employee
212 Views

 

It looks like Microsoft doesn't require the template keyword (but should). Since there's no way of knowing whether StaticInterfaceCast is a template or not (because the type of p is a dependent template) the template keyword is required. The fix/workaround will require with our compiler, GNU, and Microsoft. The code as is will only compile with Microsoft.

A workaround/fix is:

template <typename T, typename interfaceT>  struct HasStaticInterfaceCast
  {
    typedef char true_t;
    typedef char false_t;
    template <typename _1> static false_t Test(...);
    template <typename _1> static true_t Test(_1* p,
#ifdef OK
            decltype(p->template StaticInterfaceCast<interfaceT>())* = nullptr);
#else
            decltype(p->StaticInterfaceCast<interfaceT>())* = nullptr);
#endif
    static bool const value = sizeof(Test<T>((T*)0)) == sizeof(true_t);
};

Judith_W_Intel
Employee
212 Views
Ingo_L_
Beginner
212 Views

Thanks for your quick help, so I just got the syntax wrong.

If I then apply a negative check, it fails, because it tries to resolve the member function which its no there. As far as I understand it, SFINAE should no pick that Test function at all. Again no problem with msvc11, but maybe it is just another syntax problem ?

struct Negative {};

BOOST_MPL_ASSERT_NOT(HaStaticInterfaceCast<Negative,Interface>));

fails with compiler error

error #308: function "Negative::StaticInterfaceCast<interfa
ceT>() const [with interfaceT=Interface]" is inaccessible
      template <typename _1> static true_t Test(_1* p, decltype(p->template StaticInterfaceCast<interfaceT>())* = nullptr);

Any hint for that problem ?

Reply