2012-03-30 5 views
4

я следующий код демонстрации:запрещайте автоматический вывод типа

template <int i, typename T, typename U> 
T func(const U &t){return i * t;} 

template <int i, typename T> 
T func(const T &t){return 2 * i * t;} 

int main() 
{ 
     return func<1, int>(1); 
} 

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

In function ‘int main()’:             
11:23: error: call of overloaded ‘func(int)’ is ambiguous 
11:23: note: candidates are: 
2:3: note: T func(const U&) [with int i = 1, T = int, U = int] 
5:3: note: T func(const T&) [with int i = 1, T = int] 

Таким образом, очевидно, что автоматический вывод типа (для параметра шаблона U) мешает моим интересам выбора правильной версии функции шаблона (которая имеет только 2 параметра)

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

Итак, вопрос в том, есть ли возможность сообщить компилятору, чтобы он не выводил тип автоматически в этот момент (например, как-то говоря: возьмите шаблон, который имеет только 2 параметра)?

+2

Вы имеете в виду, кроме очевидного? (чтобы дать им возможность использовать шаблоны для разных имен - какой смысл иметь одно и то же имя, если вам нужно что-то сделать самому, чтобы проинструктировать компилятор, на котором можно использовать?) – Mat

+0

Ну, это был бы последний выбор, но я бы хотел функции для совместного использования одного и того же имени. – Nobody

+0

Я бы также предложил редизайн путем переименования. Для меня это кажется очень плохим запахом кода. Люди уже легко запутываются вопросом о том, какая функция перегруженного набора используется. Если что-то подобное присутствует, это делает его еще сложнее и может привести к недостижимому коду позже. – LiKao

ответ

1

Вы можете передать список инициализации, который эффективно отключает вывод (но вызывает список инициализацию параметров, которые в этом случае int имеет тот же эффект, хотя):

template <int i, typename T, typename U> 
T func(const U &t){return i * t;} 

template <int i, typename T> 
T func(const T &t){return 2 * i * t;} 

int main() 
{ 
     return func<1, int>({1}); 
} 

Но в вашем случае, если вы звоните func<N>(...), вы, кажется, хотите позвонить по второму, и если вы вызываете func<N, T>(...), вы всегда, похоже, хотите позвонить и второй, и только для func<N, T, U>(...) вы хотите позвонить первым, так что вы можете всегда отключить вычет для U, сделав для него параметр nededuced context

template <int i, typename T, typename U> 
T func(typename std::common_type<const U &t>::type t){return i * t;} 

template <int i, typename T> 
T func(const T &t){return 2 * i * t;} 

int main() 
{ 
     return func<1, int>({1}); 
} 
+0

Я думаю, что это в значительной степени то, о чем я просил. Хотя сейчас я обошел проблему, я думаю, что этот вопрос намного лучше подходит. – Nobody

4

Вы не можете отключить вывод типов, но вы можете использовать SFINAE для подавления одного из перегруженных:

template <int N, typename T, typename U> 
typename std::enable_if< !std::is_same<T,U>::value, T >::type 
func(const U & t) { 
    return i*t; 
} 

Это в основном создает шаблонную функцию, для которой замена будет выполнена, если выведенный тип U типа T, в этот момент SFINAE удалит шаблон из набора потенциальных кандидатов, а другой шаблон будет поднят.

Если у вас нет компилятора C++ 11, шаблоны enable_if и is_same просты в написании ... просто Google для них или оставьте комментарий.

+0

Это может решить мою проблему, но это не отвечает на вопрос. Может быть, у вас есть ответ на это? – Nobody

+1

Тип вывода является частью языка, и вы не можете просто отключить его. Вы можете в некоторых случаях (как выше) * отключить * перегрузку, чтобы в некоторых случаях это не учитывалось. –

+0

Возможно, я должен был использовать другую формулировку. Я не имел в виду автоматическое определение типа, но факт, что параметр шаблона устанавливается автоматически. Поэтому в основном я просил синтаксис, который сообщает компилятору: Возьмите шаблон с этой сигнатурой параметра! – Nobody

Смежные вопросы