f



Template function using template-template parameters

I'm trying to use Boost::Type_Traits two create a main template function
probe() that works for plain classes, and a specialization that works for
STL containers.

Unfortunately, the compiler only selects the main template instead of the
STL template when I pass a std::vector, for example.   Can you suggest a
modification to either function to help the compiler find the STL version?

// main template -- plain classes

template<typename T>
typename boost::enable_if< boost::is_class<T>, size_t >::type
    probe (const T &obj)
{
    // do something with the obj argument
};


// specialization -- STL containers

template <typename T, template<typename T> class CONT>
typename boost::enable_if< boost::is_class<T>, size_t >::type
    probe (const CONT<T> &cont)
{
    typename CONT<T>::iterator itr = cont.begin();
    typename CONT<T>::iterator itr_end = cont.end();

    for ( ; itr != itr_end; itr++)
    {
        // do something with *itr
    }

};

(I wonder is specialization is the right name for it, since the STL version 
has more template parameters than the main one).

Thanks for any help.
Kurt


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Kurt
6/24/2015 7:13:52 AM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8509) is leader. Post Follow

5 Replies
741 Views

Similar Articles

[PageSpeed] 56

On Wednesday, June 24, 2015 at 1:20:15 PM UTC+1, Kurt wrote:
> I'm trying to use Boost::Type_Traits two create a main template function
> probe() that works for plain classes, and a specialization that works for
> STL containers.

Using C++11 type traits and other functionalities you can first define a
trais to detect whether a type T is a "STL container" or not (actually, it
tests for begin and end). Then use this type trait in your function. A
complete example follows:

#include <type_traits>
#include <vector>
#include <iostream>

template <typename T, typename = int>
struct is_container : std::false_type {
};

template <typename T>
struct is_container<T, decltype((void) std::declval<T>().begin(), (void)
std::declval<T>().end(), 0)> : std::true_type {
};

template<typename T>
typename std::enable_if<std::is_class<T>::value && !is_container<T>::value,
size_t >::type
probe(const T &) {
    std::cout << "generic\n";
}

template <typename T>
typename std::enable_if<std::is_class<T>::value && is_container<T>::value,
size_t >::type
probe(const T &) {
    std::cout << "container\n";
}

class foo {};

int main() {
    probe(foo{});
    probe(std::vector<foo>{});
}


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Cassio
6/24/2015 1:06:45 PM
Am 24.06.2015 um 15:13 schrieb Kurt:
>
> I'm trying to use Boost::Type_Traits two create a main template function
> probe() that works for plain classes, and a specialization that works for
> STL containers.

I assume that your last category is not really restricted to the "STL", 
but that you are actually referring to class types that are 
instantiations of templates.

> Unfortunately, the compiler only selects the main template instead of the
> STL template when I pass a std::vector, for example.   Can you suggest a
> modification to either function to help the compiler find the STL version?
>
> // main template -- plain classes
>
> template<typename T>
> typename boost::enable_if< boost::is_class<T>, size_t >::type
>      probe (const T &obj)
> {
>      // do something with the obj argument
> };

This looks ok so far.

> // specialization -- STL containers
>
> template <typename T, template<typename T> class CONT>
> typename boost::enable_if< boost::is_class<T>, size_t >::type
>      probe (const CONT<T> &cont)
> {
>      typename CONT<T>::iterator itr = cont.begin();
>      typename CONT<T>::iterator itr_end = cont.end();
>
>      for ( ; itr != itr_end; itr++)
>      {
>          // do something with *itr
>      }
>
> };

This won't work for several reasons:

a) The template template parameter T within CONT shall not have the same 
name as the first template parameter (There is actually no reason at all 
to assign names to the template parameters of the template template 
parameter)
b) There exists no Standard Library container template that only has a 
single template parameter (Any default parameters wouldn't help you, 
because a template template parameter only matches the real number of 
template parameters), therefore you need to either add overloads or take 
advantage of variadic template parameters.
c) There exists only a small number of Standard Library Containers where 
the member type "iterator" refers to a constant iterator, therefore the 
initializations above of the form

typename CONT<T>::iterator itr = cont.begin();

are usually invalid.

You could try the following approach:

template <typename T, template<typename, typename...> class CONT, 
typename... U>
typename boost::enable_if<boost::is_class<T>, std::size_t>::type
     probe(const CONT<T, U...>& cont)
{
     typename CONT<T, U...>::const_iterator itr = cont.begin();
     typename CONT<T, U...>::const_iterator itr_end = cont.end();

     for ( ; itr != itr_end; itr++)
     {
         // do something with *itr
     }

     return ...;
}


> (I wonder is specialization is the right name for it, since the STL
version
> has more template parameters than the main one).

These two function templates are not specializations of each other (You 
can only have explicit specializations of function templates), they are 
just overloads.

HTH & Greetings from Bremen,

Daniel Kr�gler



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
UTF
6/24/2015 1:07:07 PM
Thanks to both of you for your replies.   I'm trying Daniel's suggestion,
but I modified it so that it only works for template-templates of at least
**two** parameters.  Supposedly it should then be instantiated for
std::vector<T, A>.  However, the template is not instantiated for
std::vector (the compiler selects first version in my original post, which
is not what I want), but it IS selected for one of my personal classes with
3 parameters (not shown below).   Is there something wrong with this?  By
the way, I am restricted to using a c++0x compiler.

template <typename T, template<typename, typename, typename...> class CONT, 
    typename A, typename... U>
typename boost::enable_if< boost::is_class<T>, size_t >::type
    probe(const CONT<T, A, U...> &cont)
{
    typename CONT<T, A, U ...>::const_iterator itr = cont.begin();
    typename CONT<T, A, U ...>::const_iterator itr_end = cont.end();

    // do something with iterator

    return cont.size();
};



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Kurt
6/26/2015 2:13:15 PM
Am 26.06.2015 um 22:13 schrieb Kurt:
>
> Thanks to both of you for your replies.   I'm trying Daniel's suggestion,
> but I modified it so that it only works for template-templates of at least
> **two** parameters.  Supposedly it should then be instantiated for
> std::vector<T, A>.  However, the template is not instantiated for
> std::vector (the compiler selects first version in my original post, which
> is not what I want), but it IS selected for one of my personal classes with
> 3 parameters (not shown below).   Is there something wrong with this?  By
> the way, I am restricted to using a c++0x compiler.

What do you consider as C++0x compiler? If this is a compiler (which 
one, btw.?) that has been created before the C++11 standard had been 
released, it's hard to tell, whether this is just a compiler error or 
something else.

> template <typename T, template<typename, typename, typename...> class CONT,
>      typename A, typename... U>
> typename boost::enable_if< boost::is_class<T>, size_t >::type
>      probe(const CONT<T, A, U...> &cont)
> {
>      typename CONT<T, A, U ...>::const_iterator itr = cont.begin();
>      typename CONT<T, A, U ...>::const_iterator itr_end = cont.end();
>
>      // do something with iterator
>
>      return cont.size();
> };

This declaration looks fine to me and should be preferred over your more 
generic overload.

But if your compiler has problems deducing the empty expansion (or 
applying proper partial ordering), you could instead *constrain* the 
version that I originally suggested, e.g. by writing it as follows:

template <typename... T>
struct not_empty
{
   enum { value = sizeof...(T) >= 1 };
   typedef not_empty type;
};

template <typename T, template<typename, typename...> class CONT, 
typename... U>
typename boost::enable_if<boost::mpl::and_<boost::is_class<T>, 
not_empty<U...>>, size_t>::type
     probe(const CONT<T, U...>& cont)
{
     typename CONT<T, U...>::const_iterator itr = cont.begin();
     typename CONT<T, U...>::const_iterator itr_end = cont.end();

     // do something with iterator

     return cont.size();
}

HTH & Greetings from Bremen,

Daniel Kr�gler






-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
UTF
6/27/2015 7:22:51 AM

> What do you consider as C++0x compiler? If this is a compiler (which 
> one, btw.?) that has been created before the C++11 standard had been 
> released, it's hard to tell, whether this is just a compiler error or 
> something else.

It is gcc 4.4.7 which supports many C++11 features but not all.   It does
support the features that you and Cassio have suggested.   I'm pretty sure
it supports the empty parameter pack expansion.

Thanks for all of your ideas -- I finally got the code to compile!

Kurt



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Kurt
6/30/2015 1:32:52 PM
Reply:

Similar Artilces:

Templates templates templates
The following compiles: #include <iostream> using std::cout; using std::endl; template< class T > struct DisplayFormat { unsigned char radix; const T* digits; T decimal_point_symbol; unsigned char digits_after_decimal_point; T comma_symbol; unsigned char digits_until_comma; }; DisplayFormat<wchar_t> us_display_format = { 10 , L"0123456789" , L'.' , 2 , L',' , 3 }; template < DisplayFormat < wchar_t > * df> //THIS LINE inline void Blah() { cout << df->digits << endl; } int main...

Specializing a template template-parameters with a template template class.
Has the standard ever considered the option of defining template of template of class? Why should it not be possible to define: template< typename T1, typename T2 > template< typename U1, typename U2, typename U3 > class Y {}; Y is a template with 2 parameters of a template with 3 parameters of a class. Which would make X< A, B > a template class with 3 parameters. The natural transform to: template< typename T1, typename T2, typename U1, typename U2, typename U3 > class X {}; is not equivalent in c++ with respect to partial specialization. The probl...

template template parameters using templatized nested classes
template template parameters using templatized nested classes I'm getting a bunch of different results from multiple compilers when using (or rather attempting to use) a templatized nested class (of a templatized outer class) as a default template template parameter. The following are some brief examples of the problems I've been encountering. The questions I'm hoping to have answered are: What is the proper way to accomplish what is implied in the following examples? What (if any) is the Standard's response? And in regards to the Standard, which compiler is doing it right?...

How to use the template member function of a template in the member function of another template class?
Hi, I have the following program. The error line is commented. I want to call _a's member function 'doit' with the template argument of function<T>. Would you please what is the correct way to do it? Thanks, Peng #include <iostream> template <typename T> struct function { T operator()() const { return T(); } }; template <typename T> struct A { template <typename F> T doit() { return F()(); } }; template <typename T> struct B { public: T doit() { return _a.doit<function<T> >();//error } p...

how to Specializations of function Templates or Overloading Function templates with Templates ?
#include <stdio.h> template<class T> class TpHello { public: int GetHash(){return 0;} protected: private: T a; }; template<class T> int HashKey(T key) { return (int)key; } //Specializations of function Templates or Overloading Function templates template<class T> int HashKey(TpHello<T> key) { return key.GetHash(); } int main() { TpHello<int> tpInt; HashKey(tpInt); return 0; } compile error in VC6 --------------------Configuration: template - Win32 Debug-------------------- Compiling... template.cpp E:\work\hellotest\template.cpp(52) : error C2...

overloading on the template parameter arity of a template template parameter
// I think that there is no way to write the template "cant_write_me" in // this example. Would love to be wrong. // one of many approaches that won't work template< template< typename > class > struct cant_write_me{}; template< template< typename, typename > class > struct cant_write_me{}; template< typename > struct arity_one{}; template< typename, typename > struct arity_two{}; cant_write_me< arity_one > instantiated_arity_one; cant_write_me< arity_two > instantiated_arity_two; Howard Gardner wrote: > // I think that ther...

template template function parameters?
I have need of a class template one of whose arguments is a function template - *not* a single instance of a template function, but the actual function template itself to be called with different argument types at different points. I expected something like: template<typename U, template<typename T> bool (pred)(T&)> struct Foo { ... X x; Y y; ... if (pred(x) && pred(y))... }; template<typename T> bool predAct(T& t) {...} Foo<int, predAct> f; but no joy. Some Googling shows class template template parameters, but no function template template pa...

Template parameters for template function
Hello All! There is following code: template < class T > void f(T const & value) { }; Is there any way to force user to specify template parameters explicitly? I want to do the following: f<int>(1); // Normal f(1); // This should give an error Any ideas?... WBR rush.william@gmail.com wrote: > Hello All! > > There is following code: > > template < class T > > void f(T const & value) > { > }; > > Is there any way to force user to specify template parameters > explicitly? I want to do the following: > f<int>(1); // Norm...

Function template as a template parameter
Is there any historic or technical reason why C++ allows a template parameter to be a class template but C++ does not allow a template parameter to be a function template ? Argument: Templates are a mechanism for type creation. A class template creates what we may think of as a data type through the instantiation of a class template. A function template creates what we may think of as a function type through the instantiation of a function template. Yet while we can pass class templates to both class templates and function templates as a template parameter, we can not pass fun...

Templates functions as template parameters
Hi, I would like to do something like this: class Type { public: template <template<typename> class Fun> void applyOnType(Fun f, void* data) { switch(type) { case 0: f<int>(data); break; case 1: f<short>(data); break; } }; Then I could call: template <typename T> void myFunction(T* data) { } DataType dt; dt.applyOnType(myFunction, data); But it doesn't work because I guess it is not possible to pass a template function in argument to a function. Furthermore, because of the template-template, it seems that Fun ...

how to use variadic template template parameters in C++0x?
Is it possible to have variadic template template parameters in C++0x? Are there any restrictions in their use? I'm trying to use variadic template template parameters in conjunction with type inference. This fails to compile. Does anyone see what the issue is? template <template <typename...> class Collection, typename Args...> void match(Collection<Args...> coll) { } .... vector<int> v; match(v); Is this impossible, or maybe is there a workaround? Thanks, Brendan Miller -- [ See http://www.gotw.ca/resources/clcm.htm for info abo...

templated function as parameter of another templated function
I have a bunch of templated functions: template <class Type_t> double f2(Type_t x) { return 2*x; } template <class Type_t> double f3(Type_t x) { return 3*x; } and a wrapper function, also templated, which I want to take f2 and f3 as arguments: template <class Type_t, double (*f)(Type_t)> double foobar(Type_t x) { double y=0, z=0; // compute something complicated from x first, // the same for all function pointers f. z = 4*x; // over-simplification here. // main computation. y=f(z); return y; } Then, void some_function(){ doubl...

template template parameters & member templates
I understand how to use a template parameter that is a class template, but is there a reliable way to use a member template through a template parameter. Here's an example: //////////////////////////////////////////// class TestExecutor { public: void execute1() { } template <typename T> void execute2(const T& v) { } template <typename T> void execute3() { } }; template <typename T, typename Executor> class Wrapper { public: static void dispatch(Executor& exec) { exec.execute1(); T v; exec.execute2...

Partial specialization template with template template parameter
Hi, I have write the following code example: template <typename T, template <typename> class CONTAINER, int I> class MyTemplate; template <typename T, template <typename> class CONTAINER> class MyTemplate<T, CONTAINER, 0> { }; template <typename T, template <typename> class CONTAINER> class MyTemplate<T, CONTAINER, 1> { }; And I'll like to know if this is a valid ANSI C++ syntax (e.g. can a template that have template template parameter by in a partial specialization?) I try to compile the code on...

Web resources about - Template function using template-template parameters - comp.lang.c++.moderated

Contest: Win a Template from Template Monsters
You probably already heard about TemplateMonster , right? It’s the largest online marketplace for website templates, be it WordPress themes ( ...

Resources last updated: 1/25/2016 12:55:07 PM