有人可以向我解释为什么gcc输出此错误?
/media/projects/src/libs/GUIElements/include/GUIElements/TemplatedFlagManager.h:195:
error: ‘ClearQueue’ was not declared in this scope
ClearQueue<QueueType>();
^
/media/projects/src/libs/GUIElements/include/GUIElements/TemplatedFlagManager.h:35: error:
‘typename std::enable_if<(I < sizeof... (Tp)), void>::type for_each(std::tuple<_Args2 ...>&, FuncT)
[with long unsigned int I = 1ul; FuncT = FlagNotifier<Args>::AddSubscriber(QSharedPointer<FlagSubscriber>)
[with Args = {SystemFlags::EAppFlags, SystemFlags::EQueueFlags, SystemFlags::EMessageFlags}]::<lambda(auto:2)>;
Tp = {QList<SystemFlags::EAppFlags>, QList<SystemFlags::EQueueFlags>, QList<SystemFlags::EMessageFlags>};
typename std::enable_if<(I < sizeof... (Tp)), void>::type = void]’,
declared using local type ‘FlagNotifier<Args>::AddSubscriber(QSharedPointer<FlagSubscriber>)
[with Args = {SystemFlags::EAppFlags, SystemFlags::EQueueFlags, SystemFlags::EMessageFlags}]::<lambda(auto:2)>’,
is used but never defined [-fpermissive]
for_each(std::tuple<Tp...>& t, FuncT f)
^
在此代码中:
template <typename... Args>
class FlagNotifier
{
....
void AddSubscriber(QSharedPointer<FlagSubscriber> sub)
{
for_each(flagQueues, [&](auto queue){
using QueueType = typename decltype(queue)::value_type;
for(auto flag : queue)
{
auto& group = std::get<get_index<QueueType, Args...>::value>(flagGroups);
group[flag].push_back(sub);
}
ClearQueue<QueueType>();
sub->ApplyState();
});
}
template <typename T>
void ClearQueue(){
auto& flagQueue = std::get<get_index<T, Args...>::value>(this->flagQueues);
flagQueue.clear();
}
std::tuple<QList<Args>...> flagQueues;
std::tuple<QHash<Args, QList<QSharedPointer<FlagSubscriber>>>...> flagGroups;
}
MSVC完全可以。"自动队列"实际上是元组的成员
std::tuple<QList<Args>...> flagQueues;
因此,该类型应该很容易推论,但这种晦涩的警告...
P.S。
for_each是从这个问题中获取的:stackoverflow.com/a/6894436/1143162
get_index来自以下内容:stackoverflow.com/a/18063608/1143162
ClearQueue<QueueType>();
被视为非依赖性名称,而您希望它将其视为依赖。
更改为
this->template ClearQueue<QueueType>();
应该解决您的问题。
正确解析表达式需要额外的template
。
现在回答问题。JAROD42已经提到了什么是错误的,我会尝试解释为什么。
flagnotifier是模板类。当您调用其成员函数Clearqueue时,在某些情况下,编译器可能不清楚它应该是对成员函数或免费函数Clearqueue的调用(假设您有一个(。
让我们看这个更简单的玩具示例:
#include <iostream>
template<typename T>
struct B {
int f();
};
template<typename T>
struct D : B<T> {
int g();
};
template<typename T>
int D<T>::g() {
return f(); // error: should be ‘this->f()’
}
int main()
{
return 0;
}
之所
template<>
struct B<int> {
};
那么以下代码将被打破:
D<int> d;
d.g();
因此,在这种情况下,C 标准需要使用 this-> 明确。
现在,为什么视觉工作室不抱怨?因为它不符合有关此规则的标准。原因是在C 标准中的模板专业规则稳定之前很久就引入了该编译器,后来在Microsoft上不愿破坏向后兼容性。在Visual C 2017中,他们引入了一个特殊的标志/宽容,该标志可以执行此规则,以及许多其他规则,您可以在此处查看详细信息。
另外,您可以在链接中找到此玩具示例:
- 在Visual Studio 2017中编译
- 未能在Clang 3.8.0 中编译
- 未能在GCC 5.4.0中编译