Using SFINAE to detect POD-ness of a type in C++

The original title here was Workaround for SFINAE bug in VS2005 C++

This is tentative use of SFINAE to make the equivalent for the is_pod template class that exists in TR1 (In VS2005 there's no TR1 yet). It should have its value member true when the template parameter is a POD type (including primitive types and structs made of them) and false when it's not (like with non-trivial constructors).

template <typename T> class is_pod
{
  public:

    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(int)
    {
      union {T validPodType;} u;
    }
    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(0)) == sizeof(Yes))};
};

class NonPOD
{
  public:
    NonPod(const NonPod &);
    virtual ~NonPOD();
};

int main()
{
  bool a = is_pod<char>::value;
  bool b = is_pod<NonPOD>::value;
  if (a) 
    printf("char is POD\n");
  if (b)
    printf("NonPOD is POD ?!?!?\n");
  return 0;
}

The problem is, not only VS 2005 doesn't have TR1, it won't care about the union above (which shouldn't be valid when the template parameter is not a POD), so both a and b evaluate to true.


Thanks for the answers posted below. After reading carefully them (and the code) I realized that what I was trying to do was really a wrong approach. The idea was to combine SFINAE behavior with an adaptation to the template *must_be_pod* (which I found in the book Imperfect C++, but it can be found in another places, too). Actually, this would require a quite particular set of rules for SFINAE, which are not what the standard defines, obviously. This is not really a bug in VS, after all.

Answers


The biggest problem with your approach is you don't do SFINAE here - SFINAE only applies to parameter types and return type here.

However, of all the SFINAE situations in the standard, none applies to your situation. They are

  • arrays of void, references, functions, or of invalid size
  • type member that is not a type
  • pointers to references, references to references, references to void
  • pointer to member of a non-class type
  • invalid conversions of template value parameters
  • function types with arguments of type void
  • const/volatile function type

That's probably why in Boost documentation, there is:

Without some (as yet unspecified) help from the compiler, ispod will never report that a class or struct is a POD; this is always safe, if possibly sub-optimal. Currently (May 2005) only MWCW 9 and Visual C++ 8 have the necessary compiler-_intrinsics.


This doesn't work with VS2008 either, but I suspect you knew that too. SFINAE is for deducing template arguments for template parameters; you can't really deduce the type of something that reveals the constructor-ness of a type, even though you can create a type that is incompatible with another type (i.e., unions can't use non-POD).

In fact, VS 2008 uses compiler support for traits to implement std::tr1::type_traits.


I'm not sure about the way you're trying to do SFINAE here, since is_pod<T>::test(...) will match is_pod<T>::test(0) too. Perhaps if you use a different type instead of 'int' you'd get a better match:

template <typename T> class is_pod
{
  struct my_special_type { };
  public:
    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(my_special_type)
    {
      union {T validPodType;} u;
    }

    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(my_special_type())) == sizeof(Yes))};
};

You might also want to look at Boost.Enable_if to do your SFINAE for you -- unless you're trying to implement your own library or for some reason.


Need Your Help

is it possible to “merge” two table borders into one another?

html css table border

I have given both of my tables the same styling to create a 1px border, but the problem is that when the two tables are touching each other the bottom border from the top table and the top border f...

iToggle for jQuery : Not working Properly

jquery plugins toggle easing

i am trying to use jQuery iToggle Plugin for one of my projects. But it does not seem to work correctly. Let's get to the code first, then i'd explain the problems.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.