views:

446

answers:

2

Imagine I have a template function like this:

template<typename Iterator>
void myfunc(Iterator a, typename Iterator::value_type b)
{ ... }

Is there a way to implement the same thing by declare a typedef for Iterator::valuetype that I can use in the function signature? For example, I'd prefer to be able to do something like this:

template<
    typename Iterator,
    typedef Iterator::value_type type>
void myfunc(Iterator a, type b)
{ ... }

Thus far, I've resorted to using default template arguments and Boost concept checking to ensure the default is always used:

template<
    typename Iterator,
    typename type = typename Iterator::value_type >
void myfunc(Iterator a, type b)
{
     BOOST_STATIC_ASSERT((
         boost::is_same<
             typename Iterator::value_type, 
             type
         >::value
     ));
     ...
}

...but it would be nice if there was support in the language for this type of thing.

Edit

I probably should have used a class instead of a function, since default arguments aren't standard for functions.

template<
    typename T,
    typename V = typename T::value_type>
class A : public B<T, V>  
{
    BOOST_STATIC_ASSERT((boost::is_same<typename T::value_Type, V>::type));
};
+1  A: 

You can use typename in the parameter list:

template <typename Iterator>
void myfunc(Iterator a, typename Iterator::value_type b)
{ 
}
James McNellis
Oh, the missing typename is a bug in my example, thanks for catching that. However, that's not the question I'm trying to answer. What I'd really like is to make the function signature less verbose by using a typedef for b.
redmoskito
@redmoskito: I'm not sure I understand what you are looking to accomplish. Your second code snippet is longer than the first, and the third is comparatively humongous. Looking solely at verbosity, the first is the best option. To the best of my knowledge, it is also your only option. There's no way to accomplish what you show in the second snippet and the third snippet, while allowable in C++0x, is not valid in C++03 (only class template can have default template arguments in C++03).
James McNellis
you might ending up making less verbose but IMO getting rid of the explicit type for your iterator from teh function signature will make it less clear unless you chose something better worded than just 'type'
hhafez
@redmoskito: I suppose, if you had multiple parameters that were all of the same dependent type, it could shorten the declaration, so I can sort of see what you are trying to accomplish. I still don't think there is a way to accomplish it, though.
James McNellis
@James Obviously this is a trivial example. Consider the situation in which I have 10 parameters of type Iterator::value_type -- the technique in my second code snipped would be much shorter. The third example has more code, but it achieves the conciseness of signature that I'm looking for. This is for library code, so more verbose implementation is okay if the interface is simplified.
redmoskito
@redmoskito: I see what you're getting at. I still think it's cleaner to type out the dependent typename for each of the parameters. It makes the type relationships between the parameters clearer and leaves less room for confusion.
James McNellis
@James How am I supposed to hang myself if C++ refuses to give me any rope?? ;-) Thanks for the advice
redmoskito
+2  A: 

You are looking for a templated typedef to be used inside a templated function definition. I don't think you can do that...

You can have a templated class with a static function & typedefs... But using it gets ugly:

template<typename Iterator>
class arbitraryname
{
public:
  typedef typename Iterator::value_type  value;

  static void myfunc( Iterator a, value b )
  {
    value c = b;
    cout << "Test" << c << endl;    
  }
};

struct Foo
{
  typedef int value_type;
};

int main()
{
  Foo f;
  myfunc<Foo>(f,2); // Old way.
  arbitraryname<Foo>::myfunc(f,3); // With templated class.
}

Personally, in this case, I'd go with a #define...

#define VALUE_TYPE  typename Iterator::value_type
template<typename Iterator>
void myfunc(Iterator a, VALUE_TYPE b)
#undef VALUE_TYPE
{
  typedef typename Iterator::value_type  bar;
  bar z = b;
  cout << "Test" << z << endl;
}

Sure #define's are ugly and sinful. But so is code that's painfully obtuse to read...

p.s. Just to be safe, you might want to add:

#ifdef  VALUE_TYPE
#error "VALUE_TYPE already defined!"
#endif
Mr.Ree