Pergunta

Acabei de criar esta nova classe:

//------------------------------------------------------------------------------
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H
//------------------------------------------------------------------------------
#include <vector>
#include <GL/GLFW.h>
//------------------------------------------------------------------------------
template<class T>
class MultithreadedVector {

    public:

        MultithreadedVector();

        void push_back(T data);

        void erase(typename std::vector<T>::iterator it);

        std::vector<T> get_container();
    private:

        std::vector<T> container_;
        GLFWmutex th_mutex_;


};
//------------------------------------------------------------------------------
#endif // MULTITHREADEDVECTOR_H_INCLUDED
//------------------------------------------------------------------------------

A definição da classe:

//------------------------------------------------------------------------------
#include "MultithreadedVector.h"
//------------------------------------------------------------------------------
using namespace std;
//------------------------------------------------------------------------------
template<class T>
MultithreadedVector<T>::MultithreadedVector() {

    th_mutex_ = glfwCreateMutex();
}

template<class T>
void MultithreadedVector<T>::push_back(T data) {

    glfwLockMutex(th_mutex_);
    container_.push_back(data);
    glfwUnlockMutex(th_mutex_);

}

template<class T>
void MultithreadedVector<T>::erase(typename vector<T>::iterator it) {

    glfwLockMutex(th_mutex_);
    container_.erase(it);
    glfwUnlockMutex(th_mutex_);
}

template<class T>
vector<T> MultithreadedVector<T>::get_container() {


    return container_;

}

Agora, o problema é que quando eu tento usá-lo no meu código como um membro estático de outra classe:

// VehicleManager.h
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

#include "MultithreadedVector.h"
#include "Vehicle.h"
class Foo {

   public:
     // stuffs
   private:
     static MultithreadedVector<Vehicle> vehicles_; 
     ...
}

#endif

Então, dentro: VehicleManager.cpp

#include "VehicleManager.h"

MultithreadedVector<Vehicle> VehicleManager::vehicles_;

void VehicleManager::Method() {

  Vehicle vehicle;
  VehicleManager::vehicles_.push_back(vehicle);

}

Mas isso não compilar :(, eu recebo este erro cada vez que msg:

C:\***\VehicleManager.cpp|188|undefined reference to `MultithreadedVector<Vehicle>::push_back(Vehicle)'|

Eu realmente não entendo por que, especialmente que eu tenha definido o membro da classe estática no escopo global de VehicleManager.cpp.

PS:. Estou usando o Code :: Blocks

Obrigado!

Foi útil?

Solução

Isso é o que vai acontecer quando se deslocam cegamente uma implementação modelo de classe para um arquivo cpp.

Para fazer esse trabalho, você deve saber exatamente para quais tipos de T você vai instanciar o modelo de classe e especificá-los no arquivo cpp.

Neste caso, colocar isso no arquivo cpp:

template class MultithreadedVector<Vehicle>;

Note que o arquivo cpp deve saber sobre Vehicle então.

Outras dicas

A maioria C ++ compiladores não permitem declarações modelo separados e definitiions modelo. Você precisa colocar a definição completa de suas classes de modelo em um único arquivo .h, e não dividi-los em arquivos e.cpp.

O código completo de execução modelo deve ser visível para o compilador no ponto em que vê o uso de modelo para que ele possa instanciar o modelo e compilá-lo em código objeto que pode ser depois ligados.

Definir o código do modelo no mesmo arquivo de cabeçalho como o modelo é declarada.

Eu acho que existem dois casos como se pode usar modelos

  1. Fornecer código genérico para um conjunto arbitrário de tipos em conformidade
  2. Fornecer código genérico para um conjunto fixo de tipos

Para o segundo, você não precisa colocar modelos para o cabeçalho: Desde que você sabe de antemão, precisamente, com que tipos seu modelo é usado. Você pode muito bem definir a função membro de um modelo de classe, ou um modelo função em uma unidade de tradução separado, sem erros de vinculador. Algumas pessoas mantêm ensinar aos outros que isso não é possível, e confundir a questão por este.

Mas eu acho que depende desses dois casos se deseja separar declaração e definição em diferentes unidades de tradução ou não.

  • Se você quiser caso de uso 1, você sempre quer ter a definição no cabeçalho (seja incluído por arquivos chamados especiais, como .ipp, .tcc ou qualquer outro). Sei apenas de uma interface C ++ que suportes de separação definição de declarações, mesmo neste caso, é que o EDG (grupo de design Edison) interface, usado pelos compiladores da Intel e Comeau, que implementar export. Essa palavra-chave é visto como um misfeature por alguns, e a maioria dos compiladores não implementá-lo.

  • E se você quiser usar o caso 2, não é bom para colocar as definições no cabeçalho, porque não haveria nenhuma razão para fazê-lo: Você só vai instanciar explicitamente as funções e classes necessárias para o conjunto fixo de tipos. Neste segundo cenário, você usar o modelo para salvar-se do fardo para manter o código possivelmente redundante, e tem a opção aberta para introduzir um comportamento especial para alguns tipos em alguns casos.

Seu cenário é claramente uma situação de caso 1, e assim você terá que colocar suas definições no cabeçalho.

Você parece ter uma cópia e colar erro no VehicleManager.h:

#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

Esta proíbe a inclusão do arquivo de cabeçalho, onde a classe Foo é definido.

Você não pode escrever a implementação do modelo no arquivo cpp na maioria dos casos. Mova a implementação de modelo para o arquivo de cabeçalho para que compilador pode instanciar-lo corretamente.

Além de outras respostas:

Você tem que get_container() guarda também. Este método basicamente copia os elementos container_ e, portanto, deve ser vigiado.

template<class T>
vector<T> MultithreadedVector<T>::get_container() 
{
    return container_;
}

Um modelo de forma é uma espécie de avançado, especializado tipo de macro. Você não pode realmente compilar uma defintion modelo separadamente, como parece que você está tentando fazer.

Para a maioria das pessoas, isso significa que eles não se incomodam mesmo para separar Tepla definições de suas declarações. Eu tenho um colega de trabalho que leva isso um passo adiante , e se recusa a separar < em> não-template definições e declarações também.

Se você quiser colocar a definição de um modelo da declaração, você tem um par de opções embora.

A primeira opção é usar o C ++ palavra-chave "exportação". O problema com esta solução aparentemente simples é que ninguém suporta . É muito difícil para escritores de compiladores de implementar.

A segunda opção é usar um terceiro tipo de arquivo , muitas vezes com a tag ".ipp", para as declarações. O truque aqui é que ele ainda é um arquivo que deve ser "#included", mas sendo um arquivo separado, você só tem que incluí-lo em arquivos ".cpp". Eu encontrei minha vinculador não gostar se eu #include um ".ipp" em mais de um arquivo ".cpp" em um único programa, então você tem que escolher um ser o includer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top