Как да специализирам тази членска функция на шаблон?

Имам тази настройка:

class DontUse;

template<class T,class U = DontUse, class V = SomeStandardType>
class Foo
{
   public:
     void bar(U &uh);
};

Когато U е настроено на DontUse, искам лентата да е празна функция. Във всички останали случаи искам лентата да има някаква реализация. Опитах се да направя това с помощта на специализация, но този код (който осъзнавам, че някак си е неправилен) не се компилира:

template<class T,class V> void Foo<T,DontUse,V>::bar(DontUse &none){}
template<class T,class U,class V> void Foo<T,U,V>::bar(U &uh)
{
  //do something here
}

Съобщението за грешка е това (MSVC10):

1>path_to_project: error C2244: 'Foo<T,U,V>::bar' : unable to match function definition to an existing declaration

и сочи към линията на първата шаблонна специализация.

Как да направя това правилно?

Ето действителния код, въпреки че е намален до минималистичната част, която е уместна:

    struct DontUse;

    template<typename Derived, typename Renderer =  DontUse, typename TimeType = long>
    class Gamestate
    {
    public:

        void Render(Renderer &r);

    };

    template<typename Derived, typename TimeType> void Gamestate<Derived, DontUse,TimeType>::Render( DontUse){}
    template<typename Derived, typename Renderer, typename TimeType> void Gamestate<Derived,Renderer,TimeType>::Render(Renderer &r)
    {
        static_cast<Derived*>(this)->Render(r);
    }

person TravisG    schedule 29.02.2012    source източник
comment
можете ли да публикувате определението на вашия специализиран клас?   -  person Nate    schedule 29.02.2012
comment
@Nate: Да, поставих го във въпроса.   -  person TravisG    schedule 29.02.2012


Отговори (3)


Не можете да специализирате отделни членове на шаблон. Трябва да специализирате самия клас:

class DontUse;

template<class T, class V>
class Foo<T, DontUse, V>
{
   public:
     void bar(DontUse)
     { }
};
person Bo Persson    schedule 29.02.2012

Препоръчвам да използвате само това:

#include <type_traits>

template <class A, class B, class C>
struct S
{
    void foo(B& b)
    {
        static_assert(!std::is_same<U, DontUse>::value, "Bad Boy!");
    }
};

Или, ако наистина искате празна функция, просто използвайте if.

#include <type_traits>

template <class A, class B, class C>
struct S
{
    void foo(B& b)
    {
         if(!std::is_same<U, DontUse>::value)
         {
              //all code goes here
         }
    }
};
person cooky451    schedule 29.02.2012
comment
Благодаря, но това не е достатъчно. Въпросът е да се даде възможност на потребителя да създаде екземпляр на Derived‹Gamestate›, който всъщност не прави никакво изобразяване (Например за сървърно програмиране). Бих могъл просто да накарам потребителя да остави тази функция внедрена, но празна, но ако го направя по моя начин, би било малко по-удобно, мисля. Между другото, ще приема отговора на Bo Persson, тъй като технически той отговори на въпроса ми по-точно (как да се специализира нещо) и даде код. - person TravisG; 29.02.2012
comment
@heishe С is_same можете да правите всичко, което искате. Хвърлете изключение, извикайте друга функция и т.н. Не виждам, че имате проблем тук. - person cooky451; 29.02.2012
comment
Да, разбирам какво имаш предвид сега. Просто направете void Render(Renderer &r) { if(is_same‹...›::value) {do nothing} else {do ​​default stuff}}. Все пак зададох последващ въпрос на този въпрос тук, който пита дали това е възможно по някакъв начин по време на компилиране: stackoverflow.com/questions/9503042/ - person TravisG; 29.02.2012
comment
Не мисля, че вашето решение ще работи в крайна сметка, тъй като в do default stuff ще трябва да използвам функции от дадения тип шаблон, които DontUse очевидно не притежава (което води до грешка при компилиране). - person TravisG; 29.02.2012
comment
Все още не разбирам проблема ви, но отговорът на другия въпрос изглежда е най-добрият, който можете да получите, така че продължете с него. Дори не знаех, че това е възможно. ;) - person cooky451; 29.02.2012

Не става така. Членска функция на шаблон на клас сама по себе си не е отделен шаблон и не може да бъде специализирана (частично или изцяло) независимо от шаблона на класа.

Трябва да дефинирате частична специализация на шаблона на класа Foo, да му дадете членска функция bar и да дефинирате това.

person Steve Jessop    schedule 29.02.2012