Источник (в конце вопроса) будет вызывать, как мне кажется, ошибку в Solaris Studio (а не на других компиляторах).
Сообщение об ошибке было переформатировано с новыми строками для ясности:
"overload.cpp", line 44: Error:
runGenEntries<std::vector<int>>(const GenEntryRuleDriven<int>&, const std::vector<int>&)
and
runGenEntries<std::vector<int>>(const GenEntryRulesDriven<int>&, const std::vector<int>&)
have same extern name
"__1cNrunGenEntries4nDstdGvector4Cin0AJallocator4Ci_____6FrkTArk1_v_".
1 Error(s) detected.
Обратите внимание, что первый параметр двух функций runGenEntries отличается только одним символом (‘s’ в конце правила)
Это, кажется, происходит, когда первый параметр имеет тип:
const typename GenEntryRulesDrivenType<typename InputsType::value_type>::type
И не происходит, когда первый параметр вместо типа:
const typename GenEntryRulesDriven<typename InputsType::value_type>
Который решает тот же тип в конце концов!
Является ли это следствием неясного правила C ++, реализованного только в Solaris? Или это ошибка Solaris Studio, которая искажает символы?
Следующий источник является компилируемым, как и на любом компиляторе.
Определение будет либо активировать код, который вызывает ошибку, либо активировать код, который должен был бы дать тот же результат (но на этот раз без ошибок):
#include <iostream>
#include <vector>
template<typename T>
struct GenEntryRulesDriven
{
void foo() const
{
}
};
template<typename T>
struct GenEntryRuleDriven
{
void bar() const
{
}
std::string toto; // to have a different size than GenEntryRulesDriven
};template <typename T>
struct GenEntryRulesDrivenType
{
typedef GenEntryRulesDriven<T> type;
};
template <typename T>
struct GenEntryRuleDrivenType
{
typedef GenEntryRuleDriven<T> type;
};
#if 1 // Gives an error
template <typename InputsType>
void runGenEntries(const typename GenEntryRulesDrivenType<
typename InputsType::value_type>::type &genEntry,
const InputsType& inputs)
{
genEntry.foo();
}
template <typename InputsType>
void runGenEntries(const typename GenEntryRuleDrivenType<
typename InputsType::value_type>::type &genEntry,
const InputsType& inputs)
{
genEntry.bar();
}
#else // No error but same types as above!
template <typename InputsType>
void runGenEntries(const typename GenEntryRulesDriven<
typename InputsType::value_type> &genEntry,
const InputsType& inputs)
{
genEntry.foo();
}
template <typename InputsType>
void runGenEntries(const typename GenEntryRuleDriven<
typename InputsType::value_type> &genEntry,
const InputsType& inputs)
{
genEntry.bar();
}
#endif
int
main()
{
std::vector<int> v;
GenEntryRulesDriven<int> rulesDriven;
runGenEntries(rulesDriven, v);
GenEntryRuleDriven<int> ruleDriven;
runGenEntries(ruleDriven, v);
return 0;
}
Этот код был скомпилирован на следующей платформе:
bash$ uname -a
SunOS pegasus 5.10 Generic_118855-33 i86pc i386 i86pc
bash$ CC -V
CC: Sun C++ 5.10 SunOS_i386 128229-07 2010/03/24
Краткий ответ: это, похоже, «нефиксированная» ошибка 6532605 (я вижу, что на нее ссылаются многочисленные поиски в Google, но я не могу открыть саму ошибку на https://support.oracle.com/rs?type=bug&ID = 6532605).
Обходной путь, который делают разработчики Qt, — поместить определение метода в отдельный модуль компиляции (файл .cpp).
Если вы разобьете имя символа, на которое жалуется CC, вы увидите, что он компилирует const __type_0& аргумент в качестве первого аргумента:
$ echo __1cNrunGenEntries4nDstdGvector4Cin0AJallocator4Ci_____6FrkTArk1_v_ | c++filt
void runGenEntries<std::vector<int> >(const __type_0&,const __type_0&)
$
С g ++ 3.4.6 на точно такой же коробке Solaris 10 символы из блока 1 раскладываются так:
runGenEntries<std, vector<int, std::allocator,<int>void> >(const GenEntryRuleDrivenType<int::value_type>::type(const GenEntryRuleDrivenType<int::value_type>&)&)
runGenEntries<std, vector<int, std::allocator,<int>void> >(const GenEntryRulesDrivenType<int::value_type>::type(const GenEntryRulesDrivenType<int::value_type>&)&)
Почему Oracle не может достичь того же, что мне не под силу.
Код Qt, на который ссылаются на эту ошибку / обходной путь: Вот.
Мы можем видеть, что есть две функции, объявленные с похожим именем:
Expression::Ptr DocFN::typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType);
Expression::Ptr IdFN::typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType);
И каждый компилируется в свой собственный источник (Вот а также Вот) чтобы обойти ошибку.
От Вот, Вы также можете скомпилировать с -Qoption ccfe -abiopt=mangle6
, С этими флагами код успешно компилируется, а символы (размеченные):
void runGenEntries<std::vector<int> >(const GenEntryRuleDrivenType<__type_0::value_type>::type&,const __type_0&)
void runGenEntries<std::vector<int> >(const GenEntryRulesDrivenType<__type_0::value_type>::type&,const __type_0&)
Проблема в том, что эта опция компиляции не поддерживается, как написано Стивом Clamage:
Наконец, у компилятора есть скрытая опция, позволяющая безоговорочно исправлять все известные ошибки. Мы не публикуем опцию, потому что
- Это нестабильно. Будущие исправления или выпуски могут изменить искажение, если будет найдено больше ошибок.
- Возможно, вам придется перекомпилировать весь код C ++, включая сторонние библиотеки, используя эту опцию.
- Если вы создаете библиотеку с этой опцией, она может быть несовместима с кодом, скомпилированным без этой опции.
- Как и все скрытые параметры, он может быть изменен или удален без уведомления.
- Мы рассматриваем эту опцию как «использовать на свой страх и риск».
Если после всех этих предостережений вы все еще хотите попробовать вариант, вот он:
-Qoption ccfe -abiopt=mangle6
Обязательно добавьте его в каждую команду CC и перекомпилируйте все.
К счастью, ни одна из системных библиотек C ++, поставляемых с Solaris или Studio, не подвержена этой ошибке или скрытому параметру, поэтому вам не нужно беспокоиться о разных версиях этих библиотек.
Других решений пока нет …