Thread: SFINAE fun (or failure...)

  1. #16
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,616
    Wouldn't evaluating opaque pointer types help solve the problem?

  2. #17
    Registered User
    Join Date
    Aug 2010
    Location
    Poland
    Posts
    733
    Oh, what they want to do is a different thing. They want to determine whether T is a complete type or not by making a metafunction. I possibly understood you wrong then. I thought that you need a mean to ensure (and only ensure) that T is complete, in which case sizeof(T) does the job (causes compile-time error). I wrapped it with static_assert so that you can use it in class scope, but obviously static_assert or such isn't needed.

  3. #18
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yep, sizeof works perfectly. I changed the code to:

    Code:
    	template<typename T>
    	struct Has_Subscribe
    	{
    		typedef char yes[1];
    		typedef char no[2];
    		template<typename C> static yes& test(size_t, decltype(&C::Subscribe));
    		template<typename C> static no& test(...);
    
    		// Sanity check; if T is an incomplete type, then we cannot determine what members it has.
    		// If T is an incomplete type, this will not compile.
    		const static bool value = sizeof(test<T>(sizeof(T), nullptr)) == sizeof(yes);
    	};
    Now I will get a compile error everytime I use it incorrectly.
    So thanks to everyone for their input. Another handy meta function has been created today to squash more bugs!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #19
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Didn't realize "CRTP" was also involved.

    Nice catch, kmdv.

    @Elysia: I realize you will not listed to me because... well because you are you, but now that you have this done, you may want to look at using normal functions and implementing your "SFINAE" primitive from that point instead of classes; several compilers have flaky support for expanding member variables from a template argument so going that route gives you a larger support surface.

    Soma

  5. #20
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    @Elysia: I realize you will not listed to me because... well because you are you, but now that you have this done, you may want to look at using normal functions and implementing your "SFINAE" primitive from that point instead of classes; several compilers have flaky support for expanding member variables from a template argument so going that route gives you a larger support surface.

    Soma
    Then do tell: how would you do it? I'm always open to suggestions.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #21
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Getting instances for decltype/sizeof checks via casting nullptr is unnecessarily verbose. Just use std::declval, or if that doesn't exist in your implementation, declare it yourself:
    Code:
    template <typename T> T declval(); // no implementation
    // Usage:
    decltype(declval<foo>().something()) return_holder;
    As long as you only use declval in unevaluated expressions, no need for an actual implementation to exist. Also, while *static_cast<foo*>(nullptr) is always an lvalue, with declval you can use declval<foo>() to get an rvalue and declval<foo&>() to get an lvalue.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #22
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    As long as you only use declval in unevaluated expressions, no need for an actual implementation to exist. Also, while *static_cast<foo*>(nullptr) is always an lvalue, with declval you can use declval<foo>() to get an rvalue and declval<foo&>() to get an lvalue.
    O_o

    I like this approach far more than using `nullptr'.

    That approach is also far more likely to work on compilers that complain about using null with `static_cast'.

    Soma

  8. #23
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Then do tell: how would you do it?
    O_o

    Before I take the effort, I'll tell you again, you'd be using normal functions.

    The public interface would then be `Subscribe(sObject, sIndex)' or similar instead of `sObject.Subscribe(sIndex)'.

    Though, you could of course use "CRTP" to forward from a method, but the goal of that approach is to remove the use of templates in the class interface. (So, no template classes in the ancestry nor any template methods.)

    The normal function approach is also slightly more complicated to implement.

    With that all in mind, do you actually want me to take the effort?

    I know in the past you'd rather use `sObject.Subscribe(sIndex)' even if it made no sense, and I do not want to waste my time with an example to explain if you are going to stick to that interface in any event.

    Soma

  9. #24
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I would use whatever is less complex, less code and more portable. My requirements in order are: work on msvc, gcc, clang, less code, portable. So as long as it works on all three major compilers, I'm not going to worry that much about portability if it means vastly reduced complexity.
    To be fair, the method used for detecting member functions is only something I have found on the internet. I haven't been able to do one myself that's any better.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #25
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I would use whatever is less complex, less code and more portable.
    O_o

    The alternative I referenced is far more portable as it works with almost every compiler that correctly supports just templates functions, but if your only interested in those compiler, then you aren't really looking for what in mind.

    To be fair, the method used for detecting member functions is only something I have found on the internet. I haven't been able to do one myself that's any better.
    You can change to an inheritance based query allowing you to completely forgo the type of the member in interest which removes the need for C++11 features while doing almost exactly the same thing. The major difference would be how the compiler deals with warnings and errors related to the function implementing the functionality built around the member you are interested in using. With the inheritance based solution, the template will try and use a specific form if any compatible name exists throwing an error if the form doesn't match was intended. With the type specific solution, you get a more specific version or the implementation falls back on a generic form.

    Soma

  11. #26
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    O_o

    The alternative I referenced is far more portable as it works with almost every compiler that correctly supports just templates functions, but if your only interested in those compiler, then you aren't really looking for what in mind.
    While I care about portability, I also care about C++11 support, as you know. I love to be at the frontlines of new language features, which is why it's important for me to use compilers that support that.
    As such, I cannot really be bothered by compilers that have poor C++ support. Since I am doing a lot of it just for fun, I also don't want to bother with so many compilers. I know that together, gcc and clang provide pretty good standard compliance and C++11 support, and hopefully soon, C++14 support.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. SATA HDD failure
    By PING in forum Tech Board
    Replies: 4
    Last Post: 12-23-2008, 12:25 AM
  2. Assertion Failure
    By osal in forum C Programming
    Replies: 11
    Last Post: 06-03-2004, 10:25 PM
  3. A miserable failure
    By Lurker in forum A Brief History of Cprogramming.com
    Replies: 33
    Last Post: 12-21-2003, 08:37 PM
  4. cin failure
    By trekker in forum C++ Programming
    Replies: 3
    Last Post: 06-20-2003, 06:05 PM
  5. Am i a Failure?
    By Failure!!! in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 05-28-2003, 11:50 AM