Проблемы с неоднородным контейнером Энди Дж при использовании шаблона посетителя:
Я читал блог Энди Джи на тему: настоящий гетерогенный контейнер на C++. Вы можете найти его страницу здесь. Я нашел это, проведя некоторые исследования на основе этого предыдущего вопроса. Поэтому я решил пойти дальше и попробовать.
Я использую Visual Studio 2017 CE v4.601055 со свойством языка Project C/C++ для стандарта языка C++, установленным на ISO C++ Latest Draft Standard (/std:c++latest)
где я использую Windows 7 x64 Home Premium на четырехъядерном компьютере Intel.
Прочитав его блог, вы обнаружите ссылки на свои работы в онлайн-компиляторе. Единственный интерес здесь - последняя ссылка на его странице, которую можно увидеть здесь.
На wandbox Энди использует эти настройки для компилятора: $ g++ prog.cc -Wall -Wextra -I/opt/wandbox/boost-1.63.0/gcc-head/include -std=gnu++2a -pedantic-errors
Есть несколько проблем или проблем, которые я в настоящее время вижу при попытке создать этот класс, и это они включают в себя <experimental/type_traits>
что использует std::experimental::is_detected<...>
внутри одного из классов как такового:
template<class T, class U>
using visit_function =
decltype( std::declval<T>().operator()(std::declval<U&>()));
template<class T, class U>
static constexpr bool has_visit_v =
std::experimental::is_detected<visit_function, T, U>::value;
Теперь, поскольку это в настоящее время стоит, у меня нет этого файла заголовка в experimental
папка. Поэтому я комментирую строку включения, а также templated static constexpr
и когда я пытаюсь скомпилировать все кажется нормально. Затем я продолжаю сборку, и она строится с 0 ошибками.
Так что теперь я начинаю работать в основном; Затем я включаю заголовочный файл, в котором находится код, и прекрасно компилирую и собираю main. Когда я начинаю добавлять некоторый код, самое первое, что вызывает у меня некоторые ошибки компилятора. Он использует лямбду для печати контейнера.
#include <vector>
#include <unordered_map>
#include <functional>
#include <iostream>
// #include <experimental/type_traits>
int main() {
auto print_container =
[]( multi_container& _in ) {
_in.visit( print_visitor{} );
std::cout << std::end;
};
system( "PAUSE" );
return 0;
}
Вот ошибки компилятора, которые он генерирует:
1>------ Build started: Project: Stackru, Configuration: Debug Win32 ------
1>main.cpp
1>c:\...\documents\visual studio 2017\projects\stackru\stackru\main.cpp(17): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(487): note: could be 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_streambuf<char,std::char_traits<char>> *)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(467): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(const void *)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(447): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long double)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(427): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(double)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(407): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(float)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(387): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned __int64)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(367): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(__int64)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(347): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned long)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(327): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(307): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned int)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(282): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(int)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(262): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned short)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(228): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(short)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(208): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(bool)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(202): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::ios_base &(__cdecl *)(std::ios_base &))'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(196): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_ios<char,std::char_traits<char>> &(__cdecl *)(std::basic_ios<char,std::char_traits<char>> &))'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(191): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_ostream<char,std::char_traits<char>> &(__cdecl *)(std::basic_ostream<char,std::char_traits<char>> &))'
1>c:\users\skilz80\documents\visual studio 2017\projects\stackru\stackru\rectangle.h(23): note: or 'std::ostream &operator <<(std::ostream &,const MyRectangle &)'
1>c:\users\skilz80\documents\visual studio 2017\projects\stackru\stackru\learner.h(79): note: or 'std::ostream &operator <<(std::ostream &,const StudentInfo &)'
1>c:\users\skilz80\documents\visual studio 2017\projects\stackru\stackru\learner.h(57): note: or 'std::ostream &operator <<(std::ostream &,const Student &)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(681): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(728): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(766): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(813): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(853): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const _Elem *)'
1> with
1> [
1> _Elem=char
1> ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(900): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,_Elem)'
1> with
1> [
1> _Elem=char
1> ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(939): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const signed char *)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(946): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,signed char)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(953): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const unsigned char *)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(960): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,unsigned char)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\ostream(1008): note: or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const std::error_code &)'
1>c:\users\skilz80\documents\visual studio 2017\projects\stackru\stackru\main.cpp(17): note: while trying to match the argument list '(std::ostream, overloaded-function)'
1>Done building project "Stackru.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Где это терпит неудачу на линии std::cout << std::endl;
в лямбде.
Затем я добавляю остальную часть кода и закомментирую лямбду и все вызовы к ней как таковые:
int main() {
/*auto print_container =
[]( multi_container& _in ) {
_in.visit( print_visitor{} );
std::cout << std::end;
}*/
multi_container c;
c.push_back( 'a' );
c.push_back( 1 );
c.push_back( 2.0 );
c.push_back( 3 );
c.push_back( std::string { "foo" } );
std::cout << "c: ";
//print_container( c );
multi_container c2 = c;
std::cout << "c2: ";
//print_container( c2 );
c.clear();
std::cout << "c after clearning c: ";
c.visit( print_visitor {} );
std::cout << std::endl;
std::cout << "c2 after clearing c: ";
//print_container( c );
c = c2;
std::cout << "c after assignment to c2: ";
//print_container( c );
my_visitor v;
std::cout << "Visiting c (should double ints & doubles)\n";
c.visit( v );
std::cout << "c: ";
//print_container( c );
struct string_visitor : visitor_base<std::string> {
void operator()( std::string& _s ) {
// append bar to all strings
_s += "bar";
}
};
std::cout << "Visiting c again (should append \"bar\" to all strings)\n";
c.visit( string_visitor {} );
std::cout << "c: ";
//print_container( c );
std::cout << "Size of c: " << c.size() << std::endl;
std::cout << "Number of integers in c: " << c.number_of<int>() << std::endl;
system( "PAUSE" );
return 0;
}
Компиляция этого не происходит в отношении этой функции
template<class T>
size_t number_of() const {
auto iter = items<T>.find( this );
if ( iter != items.cend() ) {
return items<T>[this].size();
}
return 0;
}
и эта статическая переменная шаблона:
template<class T>
static std::unordered_map<const multi_container*, std::vector<T>> items;
генерирование этих ошибок компилятора:
1>------ Build started: Project: Stackru, Configuration: Debug Win32 ------
1>main.cpp
1>c:\...\documents\visual studio 2017\projects\stackru\stackru\multi_container.h(68): error C3245: 'multi_container::items': use of a variable template requires template argument list
1>c:\...\documents\visual studio 2017\projects\stackru\stackru\multi_container.h(15): note: see declaration of 'multi_container::items'
1>c:\...\documents\visual studio 2017\projects\stackru\stackru\main.cpp(58): note: see reference to function template instantiation 'size_t multi_container::number_of<int>(void) const' being compiled
1>c:\...\documents\visual studio 2017\projects\stackru\stackru\multi_container.h(68): fatal error C1903: unable to recover from previous error(s); stopping compilation
1>Done building project "Stackru.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Мне нравится его концепция, и я хотел бы, чтобы эта работа была такой, какой она была предназначена. Единственное изменение, которое я сделал в моей IDE, - это присвоение имен структурам от его до multi
, Если я смогу заставить это работать в Visual Studio, я мог бы хотеть заменить std::unordered_map
в std::unordered_mutlimap
,
Вот мои вопросы об этом посте:
- Что нужно сделать, чтобы устранить вышеуказанные ошибки компилятора?
- Исправление
lambda
- Разрешение
number_of()
функция.
- Исправление
- Как насчет экспериментальных и
is_detected<>()
?- Есть ли вариант для этого в visual studio?
- Есть ли способ получить функциональность в
<experimental/type_traits>
? - Если нет, то что было бы эквивалентно или как трудно было бы создать мой собственный?