Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
77 Views

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

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
Highlighted
Employee
77 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);
};

0 Kudos
Highlighted
Employee
77 Views

0 Kudos
Highlighted
Beginner
77 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 ?

0 Kudos