Проблемы с неоднородным контейнером Энди Дж при использовании шаблона посетителя:

Я читал блог Энди Джи на тему: настоящий гетерогенный контейнер на 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>?
    • Если нет, то что было бы эквивалентно или как трудно было бы создать мой собственный?

0 ответов

Другие вопросы по тегам