using templates as substitutions for #ifdef

Discussion in 'C++' started by Chris Goller, Mar 8, 2005.

  1. Chris Goller

    Chris Goller Guest

    Imagine a cross platform library. A particular object wraps up
    operating system specific functionality and presents it in a uniform
    manner.

    Generally, people use ifdefs to change the functionality of a
    particular piece of code to match that of the native operating system
    (#ifdef _WINDOWS, etc)

    I'm wondering if it is possible to use templates to accomplish this
    same functionality.

    Basically, there might be something like:

    enum os_type
    {
    LINUX,
    SOLARIS,
    WINDOWS
    };

    template <os_type os>
    class os_wrapper
    {
    void os_specific_function();
    };

    template<>
    class os_wrapper<WINDOWS>
    {
    void os_specific_function()
    {
    windows_specific_function();
    }
    };

    template<>
    class os_wrapper<SOLARIS>
    {
    void os_specific_function()
    {
    solaris_specific_function();
    }

    };

    This way the compiler wouldn't need to compile the class unless it was
    instantiated with an operating system as a template argument.

    However, the code above doesn't seem to work at least in g++.

    So, my question is it possible with some template kung fu to wrap OS
    specific functions so that the compiler will compile them ONLY if they
    have been instantiated and ignore the code otherwise?

    Chris
     
    Chris Goller, Mar 8, 2005
    #1
    1. Advertising

  2. Chris Goller wrote:
    > Imagine a cross platform library. A particular object wraps up
    > operating system specific functionality and presents it in a uniform
    > manner.
    >
    > Generally, people use ifdefs to change the functionality of a
    > particular piece of code to match that of the native operating system
    > (#ifdef _WINDOWS, etc)
    >
    > I'm wondering if it is possible to use templates to accomplish this
    > same functionality.
    >
    > Basically, there might be something like:
    >
    > enum os_type
    > {
    > LINUX,
    > SOLARIS,
    > WINDOWS
    > };
    >
    > template <os_type os>
    > class os_wrapper
    > {
    > void os_specific_function();
    > };
    >
    > template<>
    > class os_wrapper<WINDOWS>
    > {
    > void os_specific_function()
    > {
    > windows_specific_function();
    > }
    > };
    >
    > template<>
    > class os_wrapper<SOLARIS>
    > {
    > void os_specific_function()
    > {
    > solaris_specific_function();
    > }
    >
    > };
    >
    > This way the compiler wouldn't need to compile the class unless it was
    > instantiated with an operating system as a template argument.
    >
    > However, the code above doesn't seem to work at least in g++.
    >
    > So, my question is it possible with some template kung fu to wrap OS
    > specific functions so that the compiler will compile them ONLY if they
    > have been instantiated and ignore the code otherwise?
    >
    > Chris
    >


    That is one method. I prefer having files containing OS specific
    implementations of functions, and letting the linker handle it all.
    The build script would choose which modules to link together.

    This helps push the OS specifics to their lowest level.

    --
    Thomas Matthews
     
    Thomas Matthews, Mar 8, 2005
    #2
    1. Advertising

  3. Chris Goller

    Chris Goller Guest

    > That is one method. I prefer having files containing OS specific
    > implementations of functions, and letting the linker handle it all.
    > The build script would choose which modules to link together.


    This is of course the traditional way of handling things. However,
    there are numerous benefits to letting the compiler rather than the
    linker know what is going on. Take the following example.

    Many libraries do mostly the same thing for all platforms. In fact,
    this is good design when developing on multiple platforms. They try to
    limit the OS-specific code to a few basic functions. Now, let's say
    I've developed a library that works on all most major operating
    systems. However, a user decides that they want to use this library on
    a 37-bit machine that isn't supported. Lets say that modifying the
    library itself would require only a few changes in one or two functions
    to make it work. The rest of the library would work just fine
    unmodified.

    The problem is that the user would have to make their own local copy of
    the library with just their changes, and change the build the process
    to accomodate their new OS. This of course now means that all updates
    to the library will require the user to reinsert his changes and build
    process changes.

    However, if this library uses templates to specify the OS then the user
    can use *template specialization* to implement changes to just the
    functions he needs to modify. No changes to the build process are
    needed.

    >This helps push the OS specifics to their lowest level.


    No, it actually pushes them to the highest level. The build process
    affects all portions of the program. Why even bother specifying the OS
    when the code itself is completely OS independent?

    The point of course is not just all this. The point is that I can't
    seem to get the method of using templates to work. That is the
    question.

    Chris
     
    Chris Goller, Mar 8, 2005
    #3
  4. The following works as expected (it displays "solaris specific
    function") on gcc 3.4.2 (MinGW, on Win XP):

    #include <iostream>

    void windows_specific_function() {
    std::cout << "windows specific function" << std::endl;
    };

    void solaris_specific_function() {
    std::cout << "solaris specific function" << std::endl;
    };


    enum os_type
    {
    LINUX,
    SOLARIS,
    WINDOWS
    };

    template <os_type os>
    class os_wrapper
    {
    public:
    void os_specific_function();

    };

    template<>
    class os_wrapper<WINDOWS>
    {
    public:
    void os_specific_function()
    {
    windows_specific_function();
    }

    };

    template<>
    class os_wrapper<SOLARIS>
    {
    public:
    void os_specific_function()
    {
    solaris_specific_function();
    }

    };

    const os_type operating_system = SOLARIS;

    int main () {

    os_wrapper<operating_system> os;

    os.os_specific_function();

    return 0;
    }


    - Jordan
     
    Jordan Stewart, Mar 8, 2005
    #4
  5. oops, I've just realised that my example doesn't really mean much:
    - You're still going to need conditional compilation for #includes (I
    don't think you'll be getting around that with template voodoo though
    :)
    - You'll still get compilation errors because of missing function
    declarations for os specific functions (which you could get around by
    providing declarations, but that creates far more work that this is all
    worth)...

    - Jordan
     
    Jordan Stewart, Mar 9, 2005
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. RJGraham
    Replies:
    6
    Views:
    483
    RJGraham
    Jun 28, 2004
  2. JKop
    Replies:
    3
    Views:
    479
  3. Replies:
    8
    Views:
    337
    Anthra Norell
    Sep 2, 2006
  4. recover
    Replies:
    2
    Views:
    812
    recover
    Jul 25, 2006
  5. Replies:
    7
    Views:
    118
    Charles DeRykus
    May 23, 2006
Loading...

Share This Page