2015-04-27 5 views
1

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

#include <iostream> 
#include <type_traits> 

using namespace std; 

unsigned long function1() { 
    return 5; 
} 
void function2() { 
    return; 
} 

template <typename Algorithm, typename enable_if<is_void<decltype(Algorithm())>::value>::type* = nullptr> 
void something(Algorithm a) { 
    std::cout << "algorithm returns void\n"; 
} 
template <typename Algorithm, typename enable_if<!is_void<decltype(Algorithm())>::value>::type* = nullptr> 
decltype(Algorithm()) something(Algorithm a) { 
    std::cout << "algorithm returns non-void: " << a() << "\n"; 
} 

int main() { 
    something(function1); 
    something(function2); 
} 

Однако это не скомпилировано. Вот сообщение сборки, которое я получаю с компилятором gcc:

||=== Build: Debug in Library (compiler: GNU GCC Compiler) ===| 
C:\Alex\Programming\C++\Library\test.cpp||In instantiation of 'decltype (Algorithm()) something(Algorithm) [with Algorithm = long unsigned int (*)(); typename std::enable_if<(! std::is_void<decltype (Algorithm())>::value), void>::type* <anonymous> = 0u; decltype (Algorithm()) = long unsigned int (*)()]':| 
C:\Alex\Programming\C++\Library\test.cpp|23|required from here| 
C:\Alex\Programming\C++\Library\test.cpp|20|warning: no return statement in function returning non-void [-Wreturn-type]| 
C:\Alex\Programming\C++\Library\test.cpp||In instantiation of 'decltype (Algorithm()) something(Algorithm) [with Algorithm = void (*)(); typename std::enable_if<(! std::is_void<decltype (Algorithm())>::value), void>::type* <anonymous> = 0u; decltype (Algorithm()) = void (*)()]':| 
C:\Alex\Programming\C++\Library\test.cpp|24|required from here| 
C:\Alex\Programming\C++\Library\test.cpp|19|error: no match for 'operator<<' in 'std::operator<< <std::char_traits<char> >((* & std::cout), ((const char*)"algorithm returns non-void: ")) << a()'| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: candidates are:| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|106|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|106|note: no known conversion for argument 1 from 'void' to 'std::basic_ostream<char>::__ostream_type& (*)(std::basic_ostream<char>::__ostream_type&) {aka std::basic_ostream<char>& (*)(std::basic_ostream<char>&)}'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|115|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ios_type& (*)(std::basic_ostream<_CharT, _Traits>::__ios_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>; std::basic_ostream<_CharT, _Traits>::__ios_type = std::basic_ios<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|115|note: no known conversion for argument 1 from 'void' to 'std::basic_ostream<char>::__ios_type& (*)(std::basic_ostream<char>::__ios_type&) {aka std::basic_ios<char>& (*)(std::basic_ios<char>&)}'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|125|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|125|note: no known conversion for argument 1 from 'void' to 'std::ios_base& (*)(std::ios_base&)'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|164|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|164|note: no known conversion for argument 1 from 'void' to 'long int'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|168|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|168|note: no known conversion for argument 1 from 'void' to 'long unsigned int'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|172|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|172|note: no known conversion for argument 1 from 'void' to 'bool'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\ostream.tcc|93|note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char; _Traits = std::char_traits<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\ostream.tcc|93|note: no known conversion for argument 1 from 'void' to 'short int'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|179|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|179|note: no known conversion for argument 1 from 'void' to 'short unsigned int'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\ostream.tcc|107|note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char; _Traits = std::char_traits<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\ostream.tcc|107|note: no known conversion for argument 1 from 'void' to 'int'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|190|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|190|note: no known conversion for argument 1 from 'void' to 'unsigned int'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|199|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|199|note: no known conversion for argument 1 from 'void' to 'long long int'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|203|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|203|note: no known conversion for argument 1 from 'void' to 'long long unsigned int'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|218|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|218|note: no known conversion for argument 1 from 'void' to 'double'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|222|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|222|note: no known conversion for argument 1 from 'void' to 'float'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|230|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|230|note: no known conversion for argument 1 from 'void' to 'long double'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|243|note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|243|note: no known conversion for argument 1 from 'void' to 'const void*'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\ostream.tcc|121|note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__streambuf_type*) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>]| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\ostream.tcc|121|note: no known conversion for argument 1 from 'void' to 'std::basic_ostream<char>::__streambuf_type* {aka std::basic_streambuf<char>*}'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\basic_string.h|2750|note: template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\basic_string.h|2750|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: mismatched types 'const std::basic_string<_CharT, _Traits, _Alloc>' and 'void'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|469|note: template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, _CharT)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|469|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: deduced conflicting types for parameter '_CharT' ('char' and 'void')| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|474|note: template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, char)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|474|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: cannot convert 'a()' (type 'void') to type 'char'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|480|note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, char)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|480|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: cannot convert 'a()' (type 'void') to type 'char'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|486|note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, signed char)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|486|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: cannot convert 'a()' (type 'void') to type 'signed char'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|491|note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, unsigned char)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|491|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: cannot convert 'a()' (type 'void') to type 'unsigned char'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|511|note: template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const _CharT*)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|511|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: mismatched types 'const _CharT*' and 'void'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\ostream.tcc|323|note: template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const char*)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\ostream.tcc|323|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: cannot convert 'a()' (type 'void') to type 'const char*'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|528|note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const char*)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|528|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: cannot convert 'a()' (type 'void') to type 'const char*'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|541|note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const signed char*)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|541|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: cannot convert 'a()' (type 'void') to type 'const signed char*'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|546|note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const unsigned char*)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|546|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|note: cannot convert 'a()' (type 'void') to type 'const unsigned char*'| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|600|note: template<class _CharT, class _Traits, class _Tp> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|600|note: template argument deduction/substitution failed:| 
C:\Alex\Programming\C++\Library\test.cpp|19|required from 'decltype (Algorithm()) something(Algorithm) [with Algorithm = void (*)(); typename std::enable_if<(! std::is_void<decltype (Algorithm())>::value), void>::type* <anonymous> = 0u; decltype (Algorithm()) = void (*)()]'| 
C:\Alex\Programming\C++\Library\test.cpp|24|required from here| 
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\ostream|600|error: forming reference to void| 
C:\Alex\Programming\C++\Library\test.cpp||In instantiation of 'decltype (Algorithm()) something(Algorithm) [with Algorithm = void (*)(); typename std::enable_if<(! std::is_void<decltype (Algorithm())>::value), void>::type* <anonymous> = 0u; decltype (Algorithm()) = void (*)()]':| 
C:\Alex\Programming\C++\Library\test.cpp|24|required from here| 
C:\Alex\Programming\C++\Library\test.cpp|20|warning: no return statement in function returning non-void [-Wreturn-type]| 
||=== Build failed: 2 error(s), 10 warning(s) (0 minute(s), 2 second(s)) ===| 

Является ли то, что я пытаюсь достичь на C++? Если да, то как?

ответ

1

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

decltype(Algorithm()()) 

или даже:

std::declval<Algorithm>()() 

, если ваш тип является функтор с недоступной по умолчанию-конструктор.

+0

Спасибо, я не знал, что вы можете создать нормальную функцию таким образом. –

+0

Можете ли вы предоставить компилируемый код, используя этот подход, при условии, что «Алгоритм» является типом функции? –

+0

@AntonSavin http://rextester.com/UWKP63034 – 0x499602D2

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