Something about template , static interface and Concept.

G

goodmen

I think the boost::concept_check is too complex.
Here is my solution about static interface and concept.

The static interface can be used as function param. It
is just a proxy of the real implementation.
And the Concept can be used when building the class
hierarchy. It is almost a private inherit, but for the sake of
providing an uniform look with the static interface version,
the private member is used.

In my opinion, the two versions of interface can be optimized
by the compiler and introduce no run-time burden.

My code need test and re-view.
Can anyone give me some advice?
Can anyone tell me whether there is a more graceful solution?
Any suggestion is welcome.


////////////////////////////////////////////////////////////////////
// Here is my code.
namespace common_utils_
{
template< typename T_Impl, bool T_UseRef >
struct si_root ;

template< typename T_Impl > struct si_root< T_Impl, true >
{
typedef T_Impl impl_t ;

si_root( void )
: m_pimpl( NULL )
{
}

void set_impl( impl_t* p )
{
m_pimpl = p ;
}

protected:
impl_t& impl( void )
{
assert( m_pimpl ) ;
return *m_pimpl ;
}

private:
impl_t* m_pimpl ;
} ;
template< typename T_Impl > struct si_root< T_Impl, false >
{
typedef T_Impl impl_t ;

protected:
impl_t& impl( void )
{
return m_impl ;
}

private:
impl_t m_impl ;
} ;

//
#define STATIC_INTERFACE_1(impl,T0) \
T0< si_root<impl,true> >

#define STATIC_INTERFACE_2(impl,T0,T1) \
T0< STATIC_INTERFACE_1(impl,T1) >

#define STATIC_INTERFACE_3(impl,T0,T1,T2) \
T0< STATIC_INTERFACE_2(impl,T1,T2) >

#define STATIC_INTERFACE_4(impl,T0,T1,T2,T3) \
T0< STATIC_INTERFACE_3(impl,T1,T2,T3) >

#define STATIC_CONCEPT_1(impl,T0) \
T0< si_root<impl,false> >

#define STATIC_CONCEPT_2(impl,T0,T1) \
T0< STATIC_CONCEPT_1(impl,T1) >

#define STATIC_CONCEPT_3(impl,T0,T1,T2) \
T0< STATIC_CONCEPT_2(impl,T1,T2) >

#define STATIC_CONCEPT_4(impl,T0,T1,T2,T3) \
T0< STATIC_CONCEPT_3(impl,T1,T2,T3) >

// exampls
namespace
{
template< typename T_Base > struct si_0 : public T_Base
{
typedef typename T_Base::impl_t::type_0 type_0 ;
void function0( void )
{
T_Base::impl().function0() ;
}
} ;
template< typename T_Base > struct si_1 : public T_Base
{
typedef typename T_Base::impl_t::type_1 type_1 ;
void function1( void )
{
T_Base::impl().function1() ;
}
} ;
template< typename T_Base > struct si_2 : public T_Base
{
typedef typename T_Base::impl_t::type_2 type_2 ;
void function2( void )
{
T_Base::impl().function2() ;
}
} ;
template< typename T_Base > struct si_3 : public T_Base
{
typedef typename T_Base::impl_t::type_3 type_3 ;
void function3( void )
{
T_Base::impl().function3() ;
}
} ;

struct TTTT
{
typedef int type_0 ;
typedef long type_1 ;
typedef float type_2 ;
typedef double type_3 ;
void function0( void )
{
std::cout << __LINE__ << ": " << __FUNCTION__ << " Is called."
<< std::endl ;
}
void function1( void )
{
std::cout << __LINE__ << ": " << __FUNCTION__ << " Is called."
<< std::endl ;
}
void function2( void )
{
std::cout << __LINE__ << ": " << __FUNCTION__ << " Is called."
<< std::endl ;
}
void function3( void )
{
std::cout << __LINE__ << ": " << __FUNCTION__ << " Is called."
<< std::endl ;
}
} ;

typedef STATIC_INTERFACE_4( TTTT, si_0, si_1, si_2, si_3 )
my_interface_t ;
typedef STATIC_CONCEPT_4( TTTT, si_0, si_1, si_2, si_3 )
my_concept_t ;

void interface_test( void )
{
TTTT obj ;
my_interface_t i ;
my_concept_t c ;

i.set_impl( &obj ) ;

i.function0() ;
i.function1() ;
i.function2() ;
i.function3() ;

c.function0() ;
c.function1() ;
c.function2() ;
c.function3() ;
}
} // anonymous

} // namespace common_utils_
 
K

kwikius

I think the boost::concept_check is too complex.
Here is my solution about static interface and concept.

The static interface can be used as function param. It
is just a proxy of the real implementation.
And the Concept can be used when building the class
hierarchy. It is almost a private inherit, but for the sake of
providing an uniform look with the static interface version,
the private member is used.

In my opinion, the two versions of interface can be optimized
by the compiler and introduce no run-time burden.

My code need test and re-view.
Can anyone give me some advice?
Can anyone tell me whether there is a more graceful solution?
Any suggestion is welcome.

<...>

Its difficult to understand from the code what you are trying to do.
Is there a particular problem that you are tring to solve?

regards
Andy Little
 
G

goodmen

Its difficult to understand from the code what you are trying to do.
Is there a particular problem that you are tring to solve?

regards
Andy Little


Because of my poor English, I think the source code is the best
way to express what i mean.

But, I was wrong!

What i want are the advices of my strange design and
ask for any more grace solutions.

Here is my explain of the code.

1, what is the term "Interface" mean ?
In C++ the traditional dynamic interface is an pure virutal
class.
It has NO any real functions, only typedef and pure virtuan
functions
in it.

// The example of dynamic interface.
class dynamic_interface
{
public:
typedef int type_0 ;
typedef long type_1 ;
typedef float type_2 ;
typedef double type_3 ;

// it is very necessary to has a virtual dector.
virtual ~dynamic_interface( void ) {}

virtual void function0( void ) = 0 ;
virtual void function1( void ) = 0 ;
virtual void function2( void ) = 0 ;
virtual void function3( void ) = 0 ;
} ;

The dynamic interface is widely used by Microsoft's COM, DirectX

2, The dynamic interface mechanism take full use of the polymorphism
of C++.
On can write the code like this to use dynamic interface.
void use_dynamic_interface( dynamic_interface* ptr )
{
if( ptr )
{
// Here, we do not know what the real type of the ptr
pointing to.
// The only thing we know is the ptr represent an object
that
// "Implemented" the interface.
}
}

3, In many circumstance, the dynamic interface is overkilled,
especially
in the realm of Generic Programming. So Boost lib and the other
Great Minds
use "static interface". I think "static interface" is just another
name of
the "Generic Concept".

4, Boost lib provide a concept_check lib to support the compil-time
checking.
But I think my solution is simpler ( But not as strong as boost. )

In my design, the "Static interface" has two version,
The one is a proxy to the real implementation class,
and the other is a "filter" to the implementation class.

The former turns any call over to the implementation
class.
The aim is to provide a stable interface to the user.
The latter filter-out any functions that do not belongs to
the
interface.

The template class si_root has two versions of partial
specialization respectively.

5, The ugly macros are designed to be used to combine many "static
interface" into one.

6, Now, here is the use of the "static interface" :

// This empty sub-class "create" a compound interface that
support the
// four static interfaces : si_0, si_1, si_2, si_3.

template< typename T >
struct my_interface
: public typedef STATIC_INTERFACE_4( T, si_0, si_1, si_2,
si_3 )
{
} ;

// Now, use the "static interface":
// NOTE:
// It is very like the function in item 2

template< typename T >
void use_dynamic_interface( my_interface<T>& i )
{
// Here, we can call any functions in the interface
// si_0, si_1, si_2, si_3.

// and use any typedefs in the inteface
// si_0, si_1, si_2, si_3.
}

7, Now, here is the use of the "Concept" version:

// I want a class that support interfaces : si_0, si_1, si_2,
si_3,
// to be the base class of my design:
template< typename T_Base >
class my_design : public STATIC_CONCEPT_4( T_Base, si_0, si_1,
si_2, si_3 )
{
// here, we can say that the base class has the following
features:
// a) it has four methods :
// void function0( void ) ;
// void function1( void ) ;
// void function2( void ) ;
// void function3( void ) ;

// b) it has four typedefs
// typedef xxx type_0 ;
// typedef xxx type_1 ;
// typedef xxx type_2 ;
// typedef xxx type_3 ;

} ;
 
K

kwikius

6, Now, here is the use of the "static interface" :

FWIW Here is my understanding of static interface. The commented out
exprs fail because they don't meet the requirements. There is another
term "named conformance" (? I think) (versus "structural conformance")
to an interface. Though technically below the names have to be
typenames rather than object or function names.

regards
Andy Little

//-----

struct a{
typedef int a_type;
};

struct b{
typedef int b_type;
};

struct ab : a,b{};


struct c {
typedef double a_type;
typedef double b_type;
};

template <typename T>
void fun_b( T const & t)
{
typedef typename T::b_type type;

type t1(1);
}

template <typename T>
void fun_a( T const & t)
{
typedef typename T::a_type type;

type t1(1);
}

int main()
{
fun_a( a());
// fun_a(b()); // error no b::a_type
fun_a(ab());
fun_a(c());

// fun_b(a()); // error n a::b_type
fun_b(b());
fun_b(ab());
fun_b(c());
}
 
G

goodmen

FWIW Here is my understanding of static interface. The commented out
exprs fail because they don't meet the requirements. There is another
term "named conformance" (? I think) (versus "structural conformance")
to an interface. Though technically below the names have to be
typenames rather than object or function names.

regards
Andy Little
hehe , I agree with you.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top