If you do not want to use boost/C++17 any, consider deriving the parameter of 'doSometing' function from a base class, and do dynamic cast to the right class object. In this case you can check in runtime that you got a valid pointer.    
class param{
public:
    virtual ~param(){};
};
template <typename T>
struct specificParam:param{
    specificParam(T p):param(p){}
    T param;
};
class Foo
{
public:
    virtual void doSomething(param* data) = 0;
};
template <typename T>
class Bar : public Foo
{
public:
    virtual void doSomething(param* data){
        specificParam<T> *p = dynamic_cast<specificParam<T> *>(data);
        if (p != nullptr){
            std::cout<<"Bar got:" << p->param << "\n";
        }
        else {
            std::cout<<"Bar: parameter type error.\n";
        }
    }
};
int main(){
  Bar<char>   obj1;
  Bar<int>    obj2;
  Bar<float>  obj3;
  specificParam<char>   t1('a');
  specificParam<int>    t2(1);
  specificParam<float>  t3(2.2);
  obj1.doSomething(&t1); //Bar got:a
  obj2.doSomething(&t2); //Bar got:1
  obj3.doSomething(&t3); //Bar got:2.2
  // trying to access int object with float parameter
  obj2.doSomething(&t3); //Bar: parameter type error.
}
The simplest (but unsafe!) way would be to use void* pointer + static cast 
class Foo
{
public:
    virtual void doSomething(void* data) = 0;
};
template <typename T>
class Bar:public Foo
{
public:
    virtual void doSomething(void* data){
        T* pData = static_cast<T*>(data);
        std::cout<<"Bar1 got:" << *pData << "\n";
    }
};
int main(){
  Bar<char>  obj1;
  Bar<int>   obj2;
  Bar<float> obj3;
  char  c = 'a';
  int   i = 1;
  float f = 2.2;
  obj1.doSomething(&c); // Bar1 got:a
  obj2.doSomething(&i); // Bar1 got:1
  obj3.doSomething(&f); // Bar1 got:2.2
  //obj2.doSomething(&c); // Very bad!!!     
}