Во многих языках есть поддержка со стороны языка 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 ) );
}