2013-12-18 3 views
0

Я новичок в вариативных шаблонах на C++, поэтому этот вопрос может показаться чем-то вроде noobish для опытных парней здесь.C++ variadic templates - NULL преобразуется в int

То, что я пытаюсь сделать, это создать proxy function, который сможет перенаправить мои аргументы на любую другую функцию, используя вариативные шаблоны.

Мой код выглядит следующим образом:

template <typename Ret, typename ... Types> 
Ret proxy_function(Types ... args) 
{ 
    return MessageBoxA(args...); 
} 

int main(int argc, char* argv[]) 
{ 
    boost::any retval = proxy_function<boost::any>(NULL, "123", "456", 0); 
} 

На компиляции, компилятор выводит следующее сообщение об ошибке:

1>Main.cpp(107): error C2664: 'int MessageBoxA(HWND,LPCSTR,LPCSTR,UINT)' : cannot convert argument 1 from 'int' to 'HWND' 

Однако, когда я поставляю следующий код работает просто отлично:

template <typename Ret, typename ... Types> 
Ret proxy_function(Types ... args) 
{ 
    return MessageBoxA(NULL, args...); 
} 

int main(int argc, char* argv[]) 
{ 
    boost::any retval = proxy_function<boost::any>("123", "456", 0); 
} 

Есть ли какая-либо причина в мире, почему компилятор не сможет применить его к типу HWND?

И еще один вопрос, который я имею в виду, прямо сейчас связанный с этой проблемой. Возможно ли определить тип аргументов внутри функции? Я хотел бы быть в состоянии сделать этот материал:

template <typename Ret, typename ... Types> 
Ret proxy_function(Types ... args) 
{ 
    psuedo-code: 
     for arg in args: 
      do_stuff<type(arg)>(arg); 
} 

Спасибо заранее, Aviv

+7

Использование 'nullptr'. Вот почему он существует. – chris

+0

Ну, для моего первого вопроса - NULL определяется также как 0, а также как (void *) 0, поэтому эти два типа не совместимы с HWND. быстрое решение этой проблемы может быть: INT основной (интермедиат ARGC, символ * ARGV []) { повышение :: любой RetVal = proxy_function ((HWND) 0, "123", "456", 0); } , но я хочу заставить мой компилятор АВТОМАТИЧЕСКИ преобразовать 0 в HWND с помощью reinterpret_cast. – CodeNinja

+0

Если у вас есть два вопроса, почему бы не задать два разных вопроса? – Yakk

ответ

3

Integral литерал значение 0 неявно преобразуется в указатель. Но в вызове он заканчивается как параметр функции времени выполнения, который не является константой времени компиляции и поэтому не конвертируется в nullpointer (даже если это 0). Используйте C++ 11 nullptr.


Кстати, найдите «идеальную пересылку».

2

NULL определяется как 0, а буква 0 неявно конвертируется в указатель. Это вызывает проблемы, подобные тем, которые вы только что упомянули, так что теперь есть новый тип nullptr_t с объектом nullptr, который неявно конвертируется в любой тип указателя и дает null (в нижнем регистре, чтобы представить концепцию null вместо того, чтобы думать, что это дало NULL).

Что касается вашего второго вопроса, в вашем конкретном использовании вы можете использовать рекурсию как так:

template <class T> 
    void do_stuff(T && t){/* stuff here with t*/} 

    template <class T, class ... Ts> 
    void do_stuff(T && t, Ts && ... ts) 
    { 
     /* do stuff with t*/ 
     do_stuff(std::forward<Ts>(ts)...); 
    } 
Смежные вопросы