Я знаю, что спецификация языка запрещает частичную специализацию шаблона функции.
Хотелось бы узнать, почему он это запрещает? Разве они не полезны?
template<typename T, typename U> void f() {} //allowed!
template<> void f<int, char>() {} //allowed!
template<typename T> void f<char, T>() {} //not allowed!
template<typename T> void f<T, int>() {} //not allowed!
template<typename T, typename U> void f(T t, U u) {}
такжеtemplate<> void f(int t, char u) {}
разрешено.Ответы:
AFAIK, который изменился в С ++ 0x.Я предполагаю, что это была просто оплошность (учитывая, что вы всегда можете получить эффект частичной специализации с более подробным кодом, поместив функцию как
static
член класса).Вы можете найти соответствующий DR (отчет о дефектах), если он есть.
РЕДАКТИРОВАТЬ : проверяя это, я обнаруживаю, что другие тоже в это верили, но никто не может найти такой поддержки в проекте стандарта. Этот поток SO, похоже, указывает на то, что частичная специализация шаблонов функций не поддерживается в C ++ 0x .
РЕДАКТИРОВАТЬ 2 : просто пример того, что я имел в виду под «помещением функции как
static
члена класса»:#include <iostream> using namespace std; // template<typename T, typename U> void f() {} //allowed! // template<> void f<int, char>() {} //allowed! // template<typename T> void f<char, T>() {} //not allowed! // template<typename T> void f<T, int>() {} //not allowed! void say( char const s[] ) { std::cout << s << std::endl; } namespace detail { template< class T, class U > struct F { static void impl() { say( "1. primary template" ); } }; template<> struct F<int, char> { static void impl() { say( "2. <int, char> explicit specialization" ); } }; template< class T > struct F< char, T > { static void impl() { say( "3. <char, T> partial specialization" ); } }; template< class T > struct F< T, int > { static void impl() { say( "4. <T, int> partial specialization" ); } }; } // namespace detail template< class T, class U > void f() { detail::F<T, U>::impl(); } int main() { f<char const*, double>(); // 1 f<int, char>(); // 2 f<char, double>(); // 3 f<double, int>(); // 4 }
источник
Что ж, вы действительно не можете выполнить частичную специализацию функции / метода, но вы можете выполнить перегрузку.
template <typename T, typename U> T fun(U pObj){...} // acts like partial specialization <T, int> AFAIK // (based on Modern C++ Design by Alexandrescu) template <typename T> T fun(int pObj){...}
Это способ, но я не знаю, удовлетворяет ли он вас.
источник
В общем, специализировать шаблоны функций не рекомендуется из-за проблем с перегрузкой. Вот хорошая статья из журнала пользователей C / C ++: http://www.gotw.ca/publications/mill17.htm
И в нем честный ответ на ваш вопрос:
источник
Поскольку вы можете частично специализировать классы, вы можете использовать функтор:
#include <iostream> template < typename dtype , int k > struct fun { int operator()() { return k ; } } ; template < typename dtype > struct fun < dtype , 0 > { int operator()() { return 42 ; } } ; int main ( int argc , char * argv[] ) { std::cout << fun<float,5>()() << std::endl ; std::cout << fun<float,0>()() << std::endl ; }
источник
()()
синтаксиса.