0

In the base.h:

template <typename T, typename T2> class Base
{
public:
    virtual int Foo(T param1) = 0;
    virtual int Bar(T param1, T2 param2) = 0;
};

In the derived1.h:

template <typename T, typename T2> class Derived1 : public Base<T, T2>
{
public:
    virtual int Foo(T param1);
    virtual int Bar(T param1, T2 param2);
};

In the derived2.h:

template <typename T, typename T2> class Derived2 : public Base<T, T2>
{
public:
    virtual int Foo(T param1);
    virtual int Bar(T param1, T2 param2);
};

In myfile.cpp:

extern "C" template<typename T, typename T2> Base<T, T2> *my_func(template<typename T, typename T2> Base<T, T2> *param)
{
    if( <cond1> )
         param<char, char> = new Derived1<char, char>();
    if( <cond2> )
        param<SQLWCHAR, SQLWCHAR> = new Derived2<SQLWCHAR, SQLWCHAR>();
    return param<T, T1>;
}

Is this code will compile in both MSVC 2010 and gcc?

I already had trouble with switching compiler, so wanted to ask first before getting there...

Also: I don't want the function to be templatized. I want the template object to be passed in and returned from the function.

Thank you.

[EDIT]

I just came home and tried:

extern "C" __declspec(dllexport) template<typename T, typename T2> Base<T, T2> *my_func(Base<T, T2> *param)

and got this:

warning C4091: '__declspec(dllexport)' : ignored on left of 'int' when no variable is declared
error C2143: syntax error : missing ';' before ''template<''

How do I make it work? The function needs to be exported and therefore it should have "C" linkage.

The other way is to define the function as C++ and grab its symbol name from the dll/so, which is painful.

[/EDIT]

[EDIT2}

What I actually had in mind is to write something like this:

class CMainFrame
{
private:
    template<typename T, typename T2> Base<T, T2> *m_pBase;
public:
    CMainFrame();
    ~CMainFrame();
    int CallFunc();
};

CMainFrame::CMainFrame() {}

CMainFrame::~CMainFrame()
{
    delete m_pBase;
}

int CMainFrame::CallFunc()
{
    template<typename T, typename T2> Base<T, T2> *base = NULL;
    m_pBase<T, T2> = my_func( base );
}

[/EDIT2]

Igor
  • 5,620
  • 11
  • 51
  • 103
  • 2
    Looks like it contains glaring syntax errors, so answer's "No." – Ulrich Eckhardt Mar 30 '16 at 15:02
  • @UlrichEckhardt, which compiler did you use? – Igor Mar 30 '16 at 15:34
  • None, hence I said "looks like". Does this code work for you? Keep in mind that templates are only fully syntax-checked and compiled when they are instantiated! – Ulrich Eckhardt Mar 30 '16 at 15:43
  • BTW: What's the deal with `extern "C"`? What would that be needed for? – Ulrich Eckhardt Mar 30 '16 at 15:46
  • @UlrichEckhardt, I just dropped the code by memory, at least the header files. Also, I didn't yet tried it - I want to make sure it will work in both environments - check here: http://stackoverflow.com/questions/36299488/only-msvc-able-to-compile-this-code. The "extern C" stuff indicates that this function will be exported. – Igor Mar 30 '16 at 15:56
  • Please compile it yourself for an easy, definite, first-hand answer. – n. m. could be an AI Mar 30 '16 at 17:53
  • @n.m., please see the edit. This is what I got with MSVC 2010 – Igor Mar 30 '16 at 23:20
  • A function template cannot have C linkage. A function template cannot be exported. A function template should almost never be defined in a .cpp file. An instantiation of a function template can be exported but still cannot have C linkage. It is not necessary to give C limkage to all exported functions. – n. m. could be an AI Mar 31 '16 at 04:47
  • @n.m., OK, so how do I resolve it? What is the best possible way? Put the function in the header file? If I remove the "C" linkage I will have to look for an unmangled name of the function, correct? – Igor Mar 31 '16 at 10:44
  • Yes, normally all templates go to header files. There are no symbols that enter object files/dlls/sos, and so no name mangling. Why would you want to look for a mangled name? Do you want to use dlsym/GetFunctionAddress? – n. m. could be an AI Mar 31 '16 at 12:24
  • @n.m., yes, I want to use dlsym/GetProcAddress. Do you know of an alternative? I can drop this into the .h file, and keep the implementation in the .cpp file, but will it fix the error? BTW did you see my first edit of how do I want it to work and what the code should look like? – Igor Mar 31 '16 at 13:53
  • You cannot keep the implementation in the CPP file, and you cannot dlsym a template. A tenplate is not a function and does not produce symbols in an object file. – n. m. could be an AI Mar 31 '16 at 16:21
  • You can write several functions *with different names* that wrap *specific* template specializations, extern-C them and export them. – n. m. could be an AI Mar 31 '16 at 16:24
  • @n.m., please see 2nd edit. With multiple functions, how do I write it? Can you put some example? – Igor Mar 31 '16 at 23:50
  • 1
    It is absolutely unclear at this point what you are trying to do. Do you want a member variable template? They don't exist. Why ate you trying to declare one? Please explain your real problem. – n. m. could be an AI Apr 01 '16 at 05:09
  • @n.m., I was hoping to instantiate a templatized object inside a dll and return it back to the main application. Then the main application will pass it to different DLLs and in the end destroy it when the application closes. However, it looks like I can't work with templates inside the dll which exports the function. So I guess I will just move the creation code into the main app and just return the pointer type to instantiate from the dll. I will try to make it work today with dll as I didn't have time yesterfay and if not that will be my solution. Thx. – Igor Apr 01 '16 at 15:34
  • @n.m., I created another thread. Please see http://stackoverflow.com/questions/36376217/proper-template-usage for explanation of what I'm after. – Igor Apr 02 '16 at 19:44

1 Answers1

0
template<typename T, typename T2> 
Base<T, T2> *my_func(Base<T, T2> *param)
{
  param = new Derived<T, T2>();
  return param;
}

or

Base<char, char> *my_func(Base<char, char> *param)
{
  param = new Derived<char, char>();
  return param;
}

Note that there doesn't seem to be any reason for param to be a parameter, if it's only being used as a local variable, so this would work better:

template<typename T, typename T2> 
Base<T, T2> *my_func()
{
  Base<T, T2> *param = new Derived<T, T2>();
  return param;
}

or

Base<char, char> *my_func()
{
  Base<char, char>* param = new Derived<char, char>();
  return param;
}

Based on OP's clarification: try this. If you really need to pass in param, you can, declaring it as Base<T,T2>* param -- but I don't think you need to. I also am not sure why you need param to be of type Base<T,T2>, because after it's compiled, it's going to be of some actual type, Base<char,char> or Base<SQWLCHAR,SQWLCHAR> or what have you. But anyway, here it is.

template<typename T, typename T2> 
Base<T, T2> *my_func()
{
    Base<T, T2>* param;

    if( <cond1> )
         param = new Derived1<char, char>();
    else if( <cond2> )
         param = new Derived2<SQLWCHAR, SQLWCHAR>();
    else
         param = ??whatever it should be if neither condition applies??;
    return param;
}

OK, based on the next clarification, this looks like what's being attempted:

class Database //an interface:  no data, function prototypes only
{
public:
   virtual QueryResultType query (const char* queryText) = 0;
   ...
};

class SQLiteDatabase: public Database
{
public:
  QueryResultType query (const char* queryText); 
  //this function has a body, and deals with queries the SQLite way
};

...

Database* myDatabase = new SQLiteDatabase ();
Topological Sort
  • 2,733
  • 2
  • 27
  • 54
  • I actually need to pass in the templatized class and inside the function instantiate the actual object with actual parameters. So I will need to pass in , inside the function instantiate an appropriate object with and return as . I have couple derived classes - where some will work with char and some with SQLWCHAR. So I need to pass a template, instantiate an object with actual type based on some condition and then return the template object. Also, I believe the last 2 version wouldn't work - I will be returning local variable which will go out of scope. – Igor Mar 30 '16 at 16:12
  • also please see edited code for clarification. This is what I have in mind. Then the caller just have the "Base" pointer. – Igor Mar 30 '16 at 16:19
  • About going out of scope: You're returning param, which is a pointer. param does go out of scope, but what it points to does not, so that'll still be there once you return. This is a conventional way of returning a dynamically allocated value. Just be sure and call `delete` on it when you're done with it! – Topological Sort Mar 30 '16 at 17:39
  • apparently I forgot that the function has to have a "C" linkage and therefore can't use templates. Please see my edit I added. Thank you. – Igor Mar 30 '16 at 23:22
  • templates are just templates, and you can't have a template _inside_ another function, nor can you declare a variable of a template type -- that is, you can't declare template MyType foo, but you can declare (say) MyType foo. – Topological Sort Apr 01 '16 at 02:19
  • Honestly, at this point, I can't tell what you're trying to accomplish here. Templates don't seem relevant here, or if they are, it's not obvious why. If you want a pointer that can point to different things w/o ignoring type checking, you'll need to make those things subclasses of the same parent type. – Topological Sort Apr 01 '16 at 02:22
  • basically I need a bunch of exported classes which have one interface and different behavior based on the different type. Then they will be instantiated from the dll and will be destroyed inside the main application. Something like this: class Database as a base class. class ODBCDatabase and class SQLiteDatabase as derived classes. SQLiteDatabase class shouldn't depend on odbc and vice versa. Hence the template usage. Only one Database instance is active at a time. – Igor Apr 01 '16 at 03:29
  • The instantiation is inside the DLL thru the base pointer. Then this base pointer is passed to the main application. When the application ends the pointer should be destroyed of course. – Igor Apr 01 '16 at 03:31
  • In essence, this is the scenario I'm looking for. Now the Database class is inside the static dll and both implementations are in dynamic ones. – Igor Apr 01 '16 at 03:32
  • Maybe you'd do best to close this question and ask another. I'll still give you a new version of what I think you want (above). Templates don't seem relevant here. – Topological Sort Apr 01 '16 at 14:37
  • just did. Please see http://stackoverflow.com/questions/36376217/proper-template-usage for explanation of what I'm after and why that solution you give won't work. – Igor Apr 02 '16 at 19:45
  • Could you tell us succinctly why it won't work? Because I looked at that other thread, and I still don't see why you want to use templates for it. – Topological Sort Apr 03 '16 at 02:59