Variadic Templates, Perfect Forwarding для функций с аргументами по умолчанию - PullRequest
11 голосов
/ 25 ноября 2011

Я использую шаблон переменной, который действует как межсетевой экран исключения в интерфейсе между C и C ++. Шаблон просто принимает функцию, затем N аргументов и вызывает функцию внутри блока try catch. Это работало нормально, к сожалению, одна из функций, которую я хочу вызвать, теперь принимает дополнительный аргумент по умолчанию. В результате имя функции не разрешается, и шаблон не компилируется.

Ошибка:

perfect-forward.cpp: в функции ‘void FuncCaller(Func, Args&& ...) [with Func = void (*)(const std::basic_string<char>&, double, const std::vector<int>&), Args = {const char (&)[7], double}]’:
perfect-forward.cpp: 69: 41: создается здесь
perfect-forward.cpp: 46: 4: ошибка: слишком мало аргументов для работы

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

template< class Func, typename ...Args >
void FuncCaller( Func f, Args&&... params )
{
   try
   {
       cout << __func__ << " called\n";
       f(params...);
   }
   catch( std::exception& ex )
   {
       cout << "Caught exception: " << ex.what() << "\n";
   }
}

void Callee( const string& arg1, double d, const vector<int>&v = vector<int>{} )
{
   cout << __func__ << " called\n";
   cout << "\targ1: " << arg1 << "\n";
   cout << "\td: " << d << "\n";
   cout << "\tv: ";
   copy( v.begin(), v.end(), ostream_iterator<int>( cout, " "  ) );
   cout << "\n";
}

int main()
{
   vector<int> v { 1, 2, 3, 4, 5 };

   FuncCaller( Callee, "string", 3.1415, v );
   FuncCaller( Callee, "string", 3.1415 );  **// Fails to compile**

   return 0;
} 

Должен ли этот код работать или я ожидаю слишком многого от компилятора?

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

т.е:.

template<typename TypeToConstruct> struct SharedPtrAllocator 
{
    template<typename ...Args> shared_ptr<TypeToConstruct> 
        construct_with_shared_ptr(Args&&... params) {
        return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...));
    };
};

работает при вызове конструктора cfollowing с 2 или 3 аргументами ...

MyClass1( const string& arg1, double d, const vector<int>&v = vector<int>{} )

1 Ответ

8 голосов
/ 25 ноября 2011

Я не думаю, что есть какой-то способ, которым это может быть достигнуто.Значения аргумента по умолчанию не являются частью сигнатуры функции.Это всего лишь короткие комбинации генерации кода, которые расширяются компилятором при буквальном вызове функции.Точно так же std::bind также не будет принимать аргументы по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...