Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7957 Discussions

Sfinae failure with template member function / decltype

Ingo_L_
Beginner
391 Views

If uisng sfinae to determine, if a member function template exists, it fails, if the function does not exists. Sfinae seems to be buggy here. With msvc11, it is no problem at all.

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, decltype(p->template StaticInterfaceCast<interfaceT>())* = nullptr);
    static bool const value = sizeof(Test<T>((T*)0)) == sizeof(true_t);
};

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);

Please Note, that I extracted this from another post, to make the issue more obvious.

0 Kudos
2 Replies
Judith_W_Intel
Employee
391 Views

 

I was able to create a small reproducer (yours had some missing pieces and relied on Boost) and have entered it into our bug tracking database as DPD200249840.

Thank you for reporting this.

I hope this represents your actual code. This compiles with MSVC++ 2010 and 2012 but not with icl.

struct Interface {};

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, decltype(p->template StaticInterfaceCast<interfaceT>())* = nullptr);
    static bool const value = sizeof(Test<T>((T*)0)) == sizeof(true_t);
};

class Negative {
private:
  template <class T> void StaticInterfaceCast() const;
};

HasStaticInterfaceCast<Negative,Interface> b;

Judy

0 Kudos
Ingo_L_
Beginner
391 Views

Well this is another facet, but it is perfectly ok, that the compiler won't be able to access a private declared member function and then fails.

The scenario I adressed, is that the class to test for the member function existance, does not have the member function at all. If it is declared private, then I would expect a compile time error, because it does not fulfill the requirements, of being publically avail.

Therefore simply having an empty class and testing that, should return false and not fail in sfiane resolution, because there is nothing to substitute at all.

struct Interface;

struct Negative {};

static_cassert(!HasStaticInterfaceCast<Negative,Interface>::value,"negative test failed");

another more degenerated use case, that will compile with msvc11 and I was yet not able to test with the current intel compiler, is that of an incomplete class. The msvc11 can handle them as well --- if by accident or intent, I am not sure what the standard states there.

struct Incomplete;

static_assert(!HasStaticInterfaceCast<Incomplete,Interface>::value,"incomplete test failed");

0 Kudos
Reply