Реализация IN, IN-OUT и OUT параметров функций
От: Galiulin Rishat Faimovich Узбекистан  
Дата: 13.09.11 14:41
Оценка: 3 (2) -2 :))) :)
Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:

specification.hpp:
#ifndef SPECIFICATION_HPP
#   define SPECIFICATION_HPP

#   include <ostream>

/**
 * @brief Functions input parameter
 */
#   define IN
/**
 * @brief Functions input/output parameter
 */
#   define IN_OUT
/**
 * @brief Functions output parameter
 */
#   define OUT

#   if 1 // in< class Type > - Functions input parameter
/**
 * @brief Functions input parameter
 * @tparam Type none reference input parameter type
 */
template< class Type >
class in
{
public:
    /**
     * Initialization constructor
     * @param value input parameter value
     */
    explicit in( const Type& value ): value_( value ) {}

    /**
     * Cast operator
     * @return input parameter value
     */
    operator const Type&() const
    {
        return value_;
    }

    /**
     * Gets parameter value
     * @return input parameter value
     */
    const Type& operator ()() const
    {
        return value_;
    }

private:
    template< class OtherType >
    in( const OtherType& value ); // disable implicit conversion for none reference objects

    /**
     * input parameter value
     */
    const Type value_;
};

/**
 * @brief Functions input parameter
 * @tparam Type reference input parameter type
 */
template< class Type >
class in< Type& >
{
public:
    /**
     * Initialization constructor
     * @param value input parameter value
     */
    explicit in( const Type& value ): value_( value ) {}

    /**
     * Cast operator
     * @return input parameter value
     */
    operator const Type&() const
    {
        return value_;
    }

    /**
     * Gets parameter value
     * @return input parameter value
     */
    const Type& operator ()() const
    {
        return value_;
    }

private:
    /**
     * input parameter value
     */
    const Type& value_;
};

/**
 * @brief Functions input parameter
 * @tparam Type pointer input parameter type
 */
template< class Type >
class in< Type* >
{
public:
    /**
     * Initialization constructor
     * @param value input parameter value
     */
    explicit in( const Type* const value ): value_( value ) {}

    /**
     * Cast operator
     * @return input parameter value
     */
    operator const Type*() const
    {
        return value_;
    }

    /**
     * Gets parameter value
     * @return input parameter value
     */
    const Type* operator ()() const
    {
        return value_;
    }

    /**
     * Member selection by pointer operator
     * @return input parameter value
     */
    const Type* operator ->() const
    {
        return value_;
    }

private:
    /**
     * input parameter value
     */
    const Type* const value_;
};
#   endif

#   if 1 // in_out< class Type& > - Functions input-output parameter
/**
 * @brief Functions input-output parameter
 * @tparam Type none pointer input-output parameter type
 */
template< class Type >
class in_out
{
public:
    /**
     * Initialization constructor
     * @param value input-output parameter value
     */
    explicit in_out( Type& value ): value_( value ) {}

    /**
     * Cast operator
     * @return input-output parameter value
     */
    operator Type&() const
    {
        return value_;
    }

    /**
     * Gets parameter value
     * @return input-output parameter value
     */
    Type& operator ()() const
    {
        return value_;
    }

    /**
     * Assignment operator
     * @param value         assignment value
     * @tparam ValueType    assignment value type
     * @return input-output parameter value
     */
    template< class ValueType >
    Type& operator =( const ValueType& value )
    {
        return value_ = value;
    }

private:
    /**
     * input-output parameter value
     */
    Type& value_;
};

/**
 * @brief Functions input-output parameter
 * @tparam Type pointer input-output parameter type
 */
template< class Type >
class in_out< Type* >
{
public:
    /**
     * Initialization constructor
     * @param value input-output parameter value
     */
    explicit in_out( Type* & value ): value_( value ) {}

    /**
     * Cast operator
     * @return input-output parameter value
     */
    operator Type* &() const
    {
        return value_;
    }

    /**
     * Gets parameter value
     * @return input-output parameter value
     */
    Type* & operator ()() const
    {
        return value_;
    }

    /**
     * Assignment operator
     * @param value         assignment value
     * @tparam ValueType    assignment value type
     * @return input-output parameter value
     */
    Type* & operator =( Type* value )
    {
        return value_ = value;
    }

    /**
     * Member selection by pointer operator
     * @return input-output parameter value
     */
    Type* operator ->() const
    {
        return value_;
    }

private:
    /**
     * input-output parameter value
     */
    Type* & value_;
};
#   endif

#   if 1 // out< class Type* > - Functions output parameter
/**
 * @brief Functions output parameter
 * @tparam Type none pointer output parameter type
 */
template< class Type >
class out
{
public:
    /**
     * Initialization constructor
     * @param value output parameter value
     */
    explicit out( Type& value ): value_( value ) {}

    /**
     * Cast operator
     * @return output parameter value
     */
    operator Type&() const
    {
        return value_;
    }

    /**
     * Gets parameter value
     * @return output parameter value
     */
    Type& operator ()() const
    {
        return value_;
    }

    /**
     * Assignment operator
     * @param value         assignment value
     * @tparam ValueType    assignment value type
     * @return output parameter value
     */
    template< class ValueType >
    Type& operator =( const ValueType& value )
    {
        return value_ = value;
    }

    /**
     * Checks if parameter is used
     * @return <code>true</code> if parameter has been set and <code>false</code> otherwise
     */
    bool used()
    {
        return ( &value_ ) != NULL;
    }

    /**
     * Checks if parameter is not used
     * @return <code>true</code> if parameter has not been set and <code>false</code> otherwise
     */
    bool not_used()
    {
        return !used();
    }

    /**
     * Creates unused parameter indicator
     * @return unused parameter indicator
     */
    static out unused()
    {
        return out( *reinterpret_cast< Type* >( NULL ) );
    }

private:
    /**
     * output parameter value
     */
    Type& value_;
};

/**
 * @brief Functions output parameter
 * @tparam Type pointer output parameter type
 */
template< class Type >
class out< Type* >
{
public:
    /**
     * Initialization constructor
     * @param value output parameter value
     */
    explicit out( Type* & value ): value_( value ) {}

    /**
     * Cast operator
     * @return output parameter value
     */
    operator Type* &() const
    {
        return value_;
    }

    /**
     * Gets parameter value
     * @return output parameter value
     */
    Type* & operator ()() const
    {
        return value_;
    }

    /**
     * Assignment operator
     * @param value         assignment value
     * @tparam ValueType    assignment value type
     * @return output parameter value
     */
    Type* & operator =( Type* value )
    {
        return value_ = value;
    }

    /**
     * Member selection by pointer operator
     * @return output parameter value
     */
    Type* operator ->() const
    {
        return value_;
    }

    /**
     * Checks if parameter is used
     * @return <code>true</code> if parameter has been set and <code>false</code> otherwise
     */
    bool used()
    {
        return ( &value_ ) != NULL;
    }

    /**
     * Checks if parameter is not used
     * @return <code>true</code> if parameter has not been set and <code>false</code> otherwise
     */
    bool not_used()
    {
        return !used();
    }

    /**
     * Creates unused parameter indicator
     * @return unused parameter indicator
     */
    static out unused()
    {
        return out( *reinterpret_cast< Type** >( NULL ) );
    }

private:
    /**
     * output parameter value
     */
    Type* & value_;
};
#   endif

/**
 * Ostream output operator
 * @param os            output stream
 * @param output        output value
 * @return output stream
 * @tparam CharType     @a os character type
 * @tparam OutputType   @a output type
 */
template< class CharType, class OutputType >
std::basic_ostream< CharType >& operator <<( in_out< std::basic_ostream< CharType > > os, const OutputType& output )
{
    return os() << output;
}

#endif /* SPECIFICATION_HPP */


А вот сравнение использования обычного и с применением in, in_out и out параметров:

main.cpp:
#include <string>
#include <iostream>
#include <stdio.h>

#include "specification.hpp"

class Base
{
public:
    virtual void print() const
    {
        std::cout << "Base" << std::endl;
    }
    virtual void operator()() const
    {
        std::cout << "Base::operator()" << std::endl;
    };
};

class Derived: public Base
{
public:
    virtual void print() const
    {
        std::cout << "Derived" << std::endl;
    }
    virtual void operator()() const
    {
        std::cout << "Derived::operator()" << std::endl;
    };
};

void function_0( const Base& paramIn )
{
    paramIn.print();
    paramIn();
}

void function_0( in< Base& > paramIn )
{
    paramIn().print();
    paramIn()();
}

void function_1( const std::string* const paramIn, int& paramInOut )
{
    printf( "%s\n", paramIn->c_str() );
    paramInOut = 21;
    printf( "%i\n", paramInOut );
    paramInOut += 34;
    printf( "%i\n", paramInOut );
}

void function_1( in< std::string* > paramIn, in_out< int > paramInOut )
{
    printf( "%s\n", paramIn->c_str() );
    paramInOut = 21;
    printf( "%i\n", paramInOut() );
    paramInOut += 34;
    printf( "%i\n", paramInOut() );
}

void function_2( const short paramIn, std::string* & paramInOut )
{
    std::string::size_type( std::string::* pCStr )() const = &std::string::size;
    paramInOut = new std::string();
    printf( "%u\n", ( paramInOut->*pCStr )() );
    printf( "%i\n", paramIn );
    printf( "%s\n", paramInOut->c_str() );
}

void function_2( in< short > paramIn, in_out< std::string* > paramInOut )
{
    std::string::size_type( std::string::* pCStr )() const = &std::string::size;
    paramInOut = new std::string();
    printf( "%u\n", ( paramInOut->*pCStr )() );
    printf( "%i\n", paramIn() );
    printf( "%s\n", paramInOut->c_str() ); ;
}

void function_3( const short* const paramIn, int* & paramInOut, int* * const paramOut = NULL )
{
    printf( "%i\n", paramIn[1] );
    if ( paramOut )
    {
        ( *paramOut )++;
    }
    paramInOut += 21;
    printf( "%i\n", *paramInOut++ );
    paramInOut += 34;
    printf( "%p\n", paramInOut );
}

void function_3( in< short* > paramIn, in_out< int* > paramInOut, out< int* > paramOut = out< int* >::unused() )
{
    printf( "%i\n", paramIn[1] );
    if ( paramOut.used() )
    {
        paramOut++;
    }
    paramInOut += 21;
    printf( "%i\n", *paramInOut++ );
    paramInOut += 34;
    printf( "%p\n", paramInOut() );
}

int main( int argc, char **argv )
{
    int Integer = argc;
    short InShort = Integer * 2;
    int InOutInteger = InShort * 3;
    std::string InString( "std::string" );
    std::string* pInOutString = &InString;
    int* pInOutInteger = &InOutInteger;
    Base b;
    Derived d;

    function_0( b );
    function_0( in< Base& >( b ) );

    function_0( d );
    function_0( in< Base& >( d ) );

    function_1( &InString, InOutInteger );
    function_1( in< std::string* >( &InString ), in_out< int >( InOutInteger ) );

    function_2( InShort, pInOutString );
    function_2( in< short >( InShort ), in_out< std::string* >( pInOutString ) );

    function_3( &InShort, pInOutInteger, &pInOutInteger );
    function_3( in< short* >( &InShort ), in_out< int* >( pInOutInteger ) , out< int* >( pInOutInteger ) );
}
in in out out параметры функций
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.