Thread: Class template that specializes- and accepts only integer and floating point types

  1. #1
    Guest
    Guest

    Class template that specializes- and accepts only integer and floating point types

    I'm trying to create a class that works with integral and floating point types, but rejects any others. I got the following to work, where the generic template gets rejected using static_assert:
    Code:
    #include <iostream>
    #include <type_traits>
    #include <utility>
    
    using namespace std;
    
    template<typename T, typename Enable = void>
    class X
    {
    static_assert(is_arithmetic_v<T>,
                  "X must be instantiated with integral or floating-point template argument.");
    };
    
    template<typename T>
    class X<T, enable_if_t<is_integral_v<T>>>
    {
    public:
        X() { cout << "X<integral type>()" << endl; }
    };
    
    template<typename T>
    class X<T, enable_if_t<is_floating_point_v<T>>>
    {
    public:
        X() { cout << "X<float type>()" << endl; }
    };
    
    class P {};
    
    int main()
    {
        X<long> x1;
        X<double> x2;
        X<P> x3; // prevented by failing static assertion
    }
    Is there a way to only use two class templates for this scenario, making the generic version redundant?

  2. #2
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    I may be wrong but I don't think so.

    You have the top-level generic version and assuming that each specialization has its own unique behavior, I think you need the generic one.

    If you can treat both floating and integral versions the same way, you can probably just use only one template which is templated std::enable_if_t<std::is_arithmetic_v<T>>

    Hmm.. Out of curiosity, what happens if you comment out your top-level class and only leave two specializations there?

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by MutantJohn View Post
    Hmm.. Out of curiosity, what happens if you comment out your top-level class and only leave two specializations there?
    You need something to specialize. Otherwise it isn't specialization.
    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. #4
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    double can perfectly contain anything long can on any 32 bit and even on some 64 bit platforms. I don't know what you plan on using X for, but depending on its use case, keep in mind that you might be better off using the most encompassing type and forgo templating.

  5. #5
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Yeah that's pretty much the way to do it. I can't think of anything neater.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    If you have access to a compiler that supports concepts, which basically means gcc 6, for now, you could probably do it with a single class.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

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

    The generic version, as shown, only exists to catch a misuse of the template.

    The `static_assert` will also catch a misuse of the template.

    You don't require both, and you don't want the generic version.

    You can simply assume the non-specialized version has the relevant property, being some integer type, because the `static_assert` would otherwise fail.

    If you are inheriting over the argument, you may need to default in order to prevent spurious warnings before the compiler sees the `static_assert` in the generic version now assuming some integer type.

    Soma

    Code:
    #include <iostream>
    #include <type_traits>
    #include <utility>
    
    using namespace std;
    
    template<typename T, typename Enable = void>
    class X
    {
    static_assert(is_arithmetic_v<T>,
                  "X must be instantiated with integral or floating-point template argument.");
    public:
        X() { cout << "X<integral type>()" << endl; }
    };
    
    template<typename T>
    class X<T, enable_if_t<is_floating_point_v<T>>>
    {
    public:
        X() { cout << "X<float type>()" << endl; }
    };
    
    class P {};
    
    int main()
    {
        X<long> x1;
        X<double> x2;
        X<P> x3; // prevented by failing static assertion
    }
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pi, floating point types and decimal places
    By jim_0 in forum C++ Programming
    Replies: 3
    Last Post: 08-13-2014, 09:48 PM
  2. Replies: 13
    Last Post: 12-04-2011, 05:36 PM
  3. Replies: 4
    Last Post: 11-01-2006, 02:23 PM
  4. Replies: 8
    Last Post: 07-24-2006, 08:14 AM
  5. Linked list with two class types within template.
    By SilasP in forum C++ Programming
    Replies: 3
    Last Post: 02-09-2002, 06:13 AM

Tags for this Thread