Шаблонное инстанцирование C++ параметров шаблона функции

Вам нужно будет использовать кисть внутри кисти, а внешняя кисть должна быть сеткой из прямоугольников 2x2 или чем-то вроде того, чтобы получить этот рисунок шахматной доски. Это должно сделать работу:


    
        
        
        
    
    
        
            
                
                    
                    
                    
                    
                
            
        
    

Результат:

enter image description here

Более быстрый метод, если вы можете уйти с его помощью - визуализировать линии шахматной доски и сетки в виде отдельных слоев. Это позволяет вам рендерить все с геометриями, а не с формами:


    
        
            
                
                    
                        
                            
                                
                                    
                                        
                                            
                                        
                                    
                                    
                                        
                                            
                                                
                                                
                                            
                                        
                                    
                                
                            
                        
                    
                    
                        
                            
                                
                                    
                                
                            
                        
                    
                
            
        
    

5
задан mavam 23 October 2008 в 00:30
поделиться

5 ответов

Ответ на это является зависимым компилятора. Некоторые версии компилятора C++ Sun обработали бы это автоматически путем создания кэша из шаблонных реализаций функции, которые будут совместно использованы через отдельные единицы перевода.

При использовании Visual C++ и какого-либо другого компилятора, который не может сделать этого, можно также поместить функциональное определение в заголовок.

Не волнуйтесь о дублирующихся определениях, если заголовок включен несколькими .cc файлами. Компилятор отмечает сгенерированные шаблоном методы со специальным атрибутом, таким образом, компоновщик знает для выбрасывания дубликатов вместо жалобы. Это - одна причина, почему C++ имеет "одно правило определения".

Править: Вышеупомянутые комментарии применяются в общем случае, где Ваш шаблон должен быть способен к соединению, учитывая любые параметры типа. Если Вы знаете замкнутое множество типов, которые будут использовать клиенты, можно удостовериться, что они доступны при помощи явного инстанцирования в файле реализации шаблона, который заставит компилятор генерировать определения для других файлов для соединения против. Но в общем случае, где Ваш шаблон должен работать с типами, возможно только известными клиенту, затем существует мало точки в разделении шаблона в заголовочный файл и и файл реализации; любой клиент должен включать обе части так или иначе. Если Вы хотите изолировать клиенты от сложных зависимостей, скрыть те зависимости позади нешаблонных функций и затем звонить в них из кода шаблона.

5
ответ дан 13 December 2019 в 22:19
поделиться

Разделение его в файлы Как Вы хочет:
Не то, чтобы я рекомендую это. Просто показ, что это возможно.

plop.h

#include <iostream>
class Foo
{
public:
    Foo(): member_(15){}


    // Note No definition of this in a header file.
    // It is defined in plop.cpp and a single instantiation forced
    // Without actually using it.
    template <typename F>
    void func(F f);

private:
    int member_;
};


struct Bar
{
     void bar_func(int val) { std::cout << val << "\n"; }
};

struct Tar
{
    void tar_func(int val) { std::cout << "This should not print because of specialisation of func\n";}
};

Plop.cpp

#include "plop.h"
#include <boost/bind.hpp>
#include <iostream>

template <typename F>
void Foo::func(F f)
{
     f(member_);
}

// Gnarly typedef
typedef boost::_bi::bind_t<void, boost::_mfi::mf1<void, Bar, int>, boost::_bi::list2<boost::_bi::value<Bar>, boost::arg<1> (*)()> > myFunc;

// Force the compiler to generate an instantiation of Foo::func()
template void Foo::func<myFunc>(myFunc f);

// Note this is not a specialization as that requires the <> after template.
// See main.cpp for an example of specialization.

main.cpp

#include "plop.h"
#include <boost/bind.hpp>
#include <iostream>

// Gnarly typedef
typedef boost::_bi::bind_t<void, boost::_mfi::mf1<void, Tar, int>, boost::_bi::list2<boost::_bi::value<Tar>, boost::arg<1> (*)()> > myTar;

// Specialization of Foo::func()
template<> void Foo::func<myTar>(myTar f)
{
    std::cout << "Special\n";
}
// Note. This is not instantiated unless it is used.
// But because it is used in main() we get a version.

int main(int argc,char* argv[])
{
    Foo f;
    Bar b;
    Tar t;

    f.func(boost::bind(&Bar::bar_func, b, _1)); // Uses instantiation from plop.cpp
    f.func(boost::bind(&Tar::tar_func, t, _1)); // Uses local specialization
}
3
ответ дан 13 December 2019 в 22:19
поделиться

Вы включаете foo.cc в caller.cc. Инстанцирование - что-то, что происходит во время компиляции - когда компилятор видит вызов в вызывающей стороне, это делает инстанцированные версии шаблонов, но должно иметь полное определение в наличии.

1
ответ дан 13 December 2019 в 22:19
поделиться

Я думаю, к чему они оба обращаются, то, что шаблонные определения функции (не только объявления) должны быть включены в файл, где они используются. Шаблонные функции на самом деле не существуют, если/до они не используются; если Вы вставляете их отдельный cc файл, то компилятор не знает о них в других cc файлах, если Вы явно #include это cc файл или в заголовочный файл или в файл, который это называет ими, из-за пути синтаксический анализатор, работает.

(Вот почему шаблон функциональные определения обычно сохраняется в заголовочных файлах как описанный Earwicker.)

Немного более ясный?

1
ответ дан 13 December 2019 в 22:19
поделиться

Я полагаю, что Earwicker корректен. Проблема с явным инстанцированием шаблонной функции членства func в этом случае состоит в том что тип, возвращенный повышением:: свяжите является зависящим от реализации. Это не повышение:: функция. Повышение:: функция может содержать boost:bind, потому что она имеет шаблонный оператор присваивания, который выводит тип правой стороны (повышение:: свяжите результат). В этом конкретном использовании func в caller.cc, с этой конкретной реализацией повышения, типом повышения:: свяжите на самом деле, они вводят упомянутый по ошибке компоновщика между <и> (т.е. boost::_bi::bind_t...). Но явно инстанцирование func для того типа, вероятно, будет иметь проблемы мобильности.

0
ответ дан 13 December 2019 в 22:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: