variadic模板代码中的GCC VS MSVC编译误差
GCC vs MSVC compilation error in variadic template code
有人可以向我解释为什么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中编译
相关文章:
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- MSVC多行宏编译器错误
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 数据成员SFINAE的C++17测试:gcc vs clang
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- MSVC是否支持C++11样式的属性而不是__declspec
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc
- 命名空间范围内的外部 - GCC vs clang vs msvc
- Visual C++: MSVC vs. GCC+CLANG: 处理 lambda 捕获类成员变量,正确的方法是什么?
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- variadic模板代码中的GCC VS MSVC编译误差
- 缩小从"int"(常量表达式)到"无符号int"的转换 - MSVC vs gc
- Clang vs MSVC:处理模板函数原型
- Clang vs GCC vs MSVC模板转换操作符-哪个编译器是正确的
- Clang vs. GCC vs. MSVC中的SFINAE和可见性检查——这是正确的
- MinGW vs MinGW- w64 vs MSVC (vc++)交叉编译
- clang vs gcc和msvc中的方法指针模板
- 错误C2027: gcc vs msvc的情况