jeudi 22 juin 2017

partial specialization of a method with variadic templated template parameter

I have a code, which compiles successfully (g++ 4.9.2):

#include <iostream>
#include <utility>

// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void
foo(T<TTs...>& arg)
{
    std::cout << "T<TTs...>" << std::endl;
}

template<typename ...Ts>
struct xxx
{
    // not important
};

// specialization for only variadic templated xxx
template<typename ...TTs> void
foo(xxx<TTs...>& arg)
{
    std::cout << "xxx<TTs...>" << std::endl;
}

// specialization for non-variadic templated xxx
template<typename TT> void
foo(xxx<TT>& arg)
{
    std::cout << "xxx<TT>" << std::endl;
}

// specialization for xxx<uint8_t>
template<> void
foo(xxx<uint8_t>& arg)
{
    std::cout << "xxx<uint8_t>" << std::endl;
}

int
main(int argc, char** argv)
{
    xxx<uint8_t> x1;
    std::cout << "xxx<uint8_t> => ";
    foo(x1);

    xxx<uint16_t> x2;
    std::cout << "xxx<uint16_t> => ";
    foo(x2);

    xxx<uint8_t,uint16_t> x3;
    std::cout << "xxx<uint8_t,uint16_t> => ";
    foo(x3);

    std::pair<uint8_t,uint16_t> x4;
    std::cout << "std::pair<uint8_t,uint16_t> => ";
    foo(x4);

    return 0;
}

and produces:

xxx<uint8_t> => xxx<uint8_t>
xxx<uint16_t> => xxx<TT>
xxx<uint8_t,uint16_t> => xxx<TTs...>
std::pair<uint8_t,uint16_t> => T<TTs...>

Now I want to have these foo methods inside a class, and write:

#include <iostream>
#include <utility>

class abc
{
public:
    // general function for any variadic templated argument
    template<template<typename ...> class T, typename ...TTs>
    void
    foo(T<TTs...>& arg)
    {
        std::cout << "T<TTs...>" << std::endl;
    }
};

template<typename ...Ts>
struct xxx
{
    // not important
};

// specialization for only variadic templated xxx
template<typename ...TTs> void
abc::foo(xxx<TTs...>& arg)
{
    std::cout << "xxx<TTs...>" << std::endl;
}

// specialization for non-variadic templated xxx
template<typename TT> void
abc::foo(xxx<TT>& arg)
{
    std::cout << "xxx<TT>" << std::endl;
}

// specialization for xxx<uint8_t>
template<> void
abc::foo(xxx<uint8_t>& arg)
{
    std::cout << "xxx<uint8_t>" << std::endl;
}

int
main(int argc, char** argv)
{
    abc p;

    xxx<uint8_t> x1;
    std::cout << "xxx<uint8_t> => ";
    p.foo(x1);

    xxx<uint16_t> x2;
    std::cout << "xxx<uint16_t> => ";
    p.foo(x2);

    xxx<uint8_t,uint16_t> x3;
    std::cout << "xxx<uint8_t,uint16_t> => ";
    p.foo(x3);

    std::pair<uint8_t,uint16_t> x4;
    std::cout << "std::pair<uint8_t,uint16_t> => ";
    p.foo(x4);

    return 0;
}

and this produces a compilation error:

test_ko.cc:24:1: error: prototype for ‘void abc::foo(xxx<TTs ...>&)’ does not match any in class ‘abc’
 abc::foo(xxx<TTs...>& arg)
 ^
test_ko.cc:10:5: error: candidate is: template<template<class ...> class T, class ... TTs> void abc::foo(T<TTs ...>&)
     foo(T<TTs...>& arg)
     ^
test_ko.cc:31:1: error: prototype for ‘void abc::foo(xxx<TT>&)’ does not match any in class ‘abc’
 abc::foo(xxx<TT>& arg)
 ^
test_ko.cc:10:5: error: candidate is: template<template<class ...> class T, class ... TTs> void abc::foo(T<TTs ...>&)
     foo(T<TTs...>& arg)

I want a specialization for foo methods, not declaring a new signature inside abc class (because there is a class with templates, a part of a library, and separate specialization, for later declared xxx class).

It looks for me that code with methods is similar to one with functions, but I get error here. What I do wrong?

Aucun commentaire:

Enregistrer un commentaire