Предотвращение создания неиспользуемых аргументов функции по умолчанию

Допустим, у меня есть функция, которая принимает указатель на функцию в качестве параметра, и этот параметр имеет аргумент по умолчанию.

template <typename T>
T* default_construct()
{
    return new T();
}

template <typename T>
void register(T* (*construct)() = default_construct<T>)
{
    // Save that function pointer for later
}

Допустим, я хочу использовать регистрацию в своем классе Foo, но Foo не имеет конструктора по умолчанию, поэтому мой default_construct не будет работать с ним. Очевидное решение состоит в том, чтобы сделать что-то вроде этого:

Foo* construct_Foo()
{
    return new Foo("String argument", 123);
}

SomeFunc()
{
    // ...
    register<Foo>(construct_Foo);
    // ...
}

Но это не работает. Несмотря на то, что register<Foo> может вызываться только в одном месте и ему передается функция для использования, default_construct<Foo> по-прежнему создается компилятором, и я получаю ошибки компилятора. Кажется, что, поскольку он никогда не используется, его следует пропустить, но я думаю, что это не так.

Есть ли способ предотвратить создание экземпляра default_construct, когда он используется в качестве аргумента по умолчанию? Единственное решение, которое я могу придумать, это поместить его в шаблон, но кажется, что должно быть лучшее решение.


person Alex    schedule 10.08.2011    source источник
comment
Вы уверены, что создан экземпляр default_construct? Честно говоря, я думал, что параметры по умолчанию будут созданы только в случае их использования. Все компиляторы, которые я пробовал, прошли следующее: ideone.com/lHfSf   -  person UncleBens    schedule 10.08.2011
comment
Следуя UncleBens, вы можете проверить символы библиотеки/исполняемого файла, чтобы убедиться, что шаблон функции был создан. Несмотря на то, что имя искажено, default_construct все равно должно появиться. Используйте nm somelib | grep default_construct и используйте c++filt для полученных символов, чтобы получить расширенную версию.   -  person Matthieu M.    schedule 10.08.2011
comment
UncleBens: Может быть, ты и прав. Я определенно получал сообщение об ошибке, которое, по-видимому, было вызвано неверным созданием экземпляра шаблона, но я просто попытался еще раз показать вам сообщение об ошибке, и на этот раз я его не получил. Должно быть, я сделал что-то еще не так, может быть, весь этот вопрос спорный. Странный. (FWIW, я использую gcc)   -  person Alex    schedule 10.08.2011


Ответы (1)


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

template <typename T>
T* default_construct()
{
    return new T();
}

template <typename T>
void register(T* (*construct)())
{
    // Save that function pointer for later
}

template<typename T>
void register()
{
    register<T>(default_construct<T>);
}

Обратите внимание, что register — это ключевое слово C++ :)

person Seth Carnegie    schedule 10.08.2011
comment
дох! Это всего лишь пример :P Фактическая функция luaW_register, но я не хотел втягивать Lua в свой вопрос. - person Alex; 10.08.2011
comment
@Alex всякий раз, когда в игру вступают аргументы по умолчанию, просто помните, что они всего лишь ярлык для перегрузки функций, и все, что можно сделать с аргументами по умолчанию, и многое другое можно сделать путем перегрузки. И получайте удовольствие от lua, это круто - person Seth Carnegie; 10.08.2011
comment
Я действительно не думал об этом таким образом, но я думаю, вы правы. Если вам интересно, это часть моей попытки улучшить эту маленькую библиотеку Lua/C++. м пишу. - person Alex; 10.08.2011
comment
@ Алекс, круто, какие улучшения ты делаешь? И да, я ненавижу использовать lua без такой оболочки. - person Seth Carnegie; 10.08.2011
comment
@ Алекс О, это ВЫ написали. Я думал, ты улучшаешь чужую обертку (не знал, что ты тот самый Алекс). Это получает закладку, я обязательно воспользуюсь ею в следующий раз, когда буду использовать lua. Хорошо сделано. - person Seth Carnegie; 10.08.2011