Как изменить количество аргументов шаблона, поддерживаемых std::tuple в MSVC++?

MSVC++ еще не поддерживает вариативные шаблоны, поэтому его стандартная библиотека «подделывает» их для таких классов, как std::tuple, с помощью макросов. Недавно я попытался скомпилировать один из своих проектов с бета-версией VC11 и получил вот это:

gtest\gtest.h(9735): error C2977: 'std::tuple' : too many template arguments
c:\program files (x86)\microsoft visual studio 11.0\vc\include\utility(72) : see declaration of 'std::tuple'
gtest\gtest.h(9743): error C2977: 'std::tuple' : too many template arguments
gtest\gtest.h(14568): error C2977: 'std::tuple' : too many template arguments
gtest\gtest.h(14568): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14568): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14568): error C2955: 'testing::internal::ParamGeneratorInterface' : use of class template requires template argument list
c:\users\billy\documents\visual studio 2010\projects\instalog\logtests\gtest\gtest.h(10076) : see declaration of 'testing::internal::ParamGeneratorInterface'
gtest\gtest.h(14570): error C2977: 'std::tuple' : too many template arguments
gtest\gtest.h(14581): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14581): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14586): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14586): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14593): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
c:\users\billy\documents\visual studio 2010\projects\instalog\logtests\gtest\gtest.h(14593) : see reference to class template instantiation 'testing::internal::CartesianProductGenerator9<T1,T2,T3,T4,T5,T6,T7,T8,T9>::Iterator' being compiled
gtest\gtest.h(14593): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14593): error C2955: 'testing::internal::ParamIteratorInterface' : use of class template requires template argument list
c:\users\billy\documents\visual studio 2010\projects\instalog\logtests\gtest\gtest.h(10003) : see declaration of 'testing::internal::ParamIteratorInterface'
gtest\gtest.h(14595): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14595): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14628): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14628): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14670): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14670): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14674): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14674): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14755): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14755): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14807): error C2977: 'std::tuple' : too many template arguments
gtest\gtest.h(14807): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14807): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14807): error C2955: 'testing::internal::ParamGeneratorInterface' : use of class template requires template argument list
gtest\gtest.h(14809): error C2977: 'std::tuple' : too many template arguments
gtest\gtest.h(14821): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14821): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14826): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14826): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14833): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
c:\users\billy\documents\visual studio 2010\projects\instalog\logtests\gtest\gtest.h(14833) : see reference to class template instantiation 'testing::internal::CartesianProductGenerator10<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>::Iterator' being compiled
gtest\gtest.h(14833): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14833): error C2955: 'testing::internal::ParamIteratorInterface' : use of class template requires template argument list
gtest\gtest.h(14835): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14835): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14871): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14871): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14917): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14917): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(14921): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(14921): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(15007): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(15007): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(15289): error C2977: 'std::tuple' : too many template arguments
gtest\gtest.h(15289): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(15289): error C2955: 'std::tuple' : use of class template requires template argument list
gtest\gtest.h(15333): error C2977: 'std::tuple' : too many template arguments
gtest\gtest.h(15333): error C3203: 'tuple' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
gtest\gtest.h(15333): error C2955: 'std::tuple' : use of class template requires template argument list

Я слышал, что есть #define, который можно где-то установить, чтобы изменить этот параметр, но я (на всю жизнь) не могу вспомнить, что это такое. Что это такое?


person Billy ONeal    schedule 06.03.2012    source источник


Ответы (3)


Вы можете определить _VARIADIC_MAX для любого значения от 5 до 10 включительно.

Этот и многие другие интересные факты о Visual C++ 11 можно найти в статье MSDN "Возможности C++11 (современный C++)." Этот конкретный макрос обсуждается в разделе, озаглавленном «Фальшивые переменные числа».

person James McNellis    schedule 06.03.2012
comment
MSVC++ сводит меня с ума! Где именно мне нужно определить _VARIADIC_MAX? Я использую CMake и создаю GTest как ОБЪЕКТ (см. здесь). - person Hindol; 23.09.2012
comment
Неважно, нашел решение add_definitions(-D_VARIADIC_MAX=10). - person Hindol; 23.09.2012

Интересная цитата из статьи blogs.msdn.com. :

Имитация вариативности. Мы разработали новую схему имитации шаблонов с вариативностью. Ранее в VC9 SP1 и VC10 мы неоднократно включали подзаголовки с макросами, определяемыми каждый раз по-разному, чтобы исключить перегрузки для 0, 1, 2, 3 и т. д. аргументов. (Например, многократно включал внутренний подзаголовок, чтобы исключить make_shared(args, args, args).) В VC11 подзаголовки исчезли. Теперь мы определяем сами вариативные шаблоны как макросы (с большим количеством обратных слешей-продолжений), а затем расширяем их с помощью мастер-макросов. Это внутреннее изменение реализации имеет некоторые заметные для пользователя эффекты. Во-первых, код более удобен в сопровождении, проще в использовании (добавление подзаголовков потребовало изрядного объема работы) и чуть менее ужасно нечитабелен. Именно это позволило нам легко реализовать вариативное размещение и должно облегчить исправление ошибок в будущем. Во-вторых, с отладчиком сложнее (извините!). В-третьих, конструктор пары pair(piecewise_construct_t, tuple, tuple) имел «интересные» эффекты. Для этого требуется N^2 перегрузок (если мы поддерживаем до 10 кортежей, это означает 121 перегрузку, так как здесь учитываются и пустые кортежи). Сначала мы заметили, что это (рассылка множества парных перегрузок, а также все перегрузки размещения) потребляет огромное количество памяти во время компиляции, поэтому в качестве обходного пути мы уменьшили бесконечность. В VC9 SP1 и VC10 бесконечность равнялась 10 (т. е. «вариативные» шаблоны поддерживали от 0 до 10 аргументов включительно). В предварительной версии VC11 для разработчиков бесконечность по умолчанию равна 5. Это вернуло потребление памяти нашим компилятором к тому, что было в VC10. Если вам нужно больше аргументов (например, у вас был код, компилируемый с помощью VC9 SP1 или VC10, в котором использовались кортежи из 6), есть выход. Вы можете определить _VARIADIC_MAX для всего проекта от 5 до 10 включительно (по умолчанию 5). Увеличение этого значения приведет к тому, что компилятор будет потреблять больше памяти, и может потребоваться использование параметра /Zm, чтобы зарезервировать больше места для PChes.

person Nawaz    schedule 06.03.2012

Это исправлено в версии 675. См. https://code.google.com/p/googletest/source/detail?r=675

person Corey Kosak    schedule 13.01.2014
comment
+1. Исправляется так же, как MSVC++ получает вариативные шаблоны :) - person Billy ONeal; 14.01.2014
comment
Хи-хи :-) Что ж, мы позаботились о том, чтобы он корректно строился и на VC 12. - person Corey Kosak; 14.01.2014
comment
Кстати, если сообщество придумало стандартный обходной путь для connect.microsoft.com/VisualStudio/feedback/details/802032/ , нам было бы интересно. В противном случае нам, вероятно, придется написать один. - person Corey Kosak; 14.01.2014