我试图理解为什么我需要在某些openCL代码中使用模板消歧器。
编辑:这是一个极小的复制案例:
//test.hpp
#include <iostream>
#include <vector>
#include "cl.hpp"
template <typename T>
class Foo {
public:
std::vector<cl::Platform> platforms;
std::vector<cl::Device> devices;
Foo();
void bar();
};
template<typename T>
Foo<T>::Foo() {
cl::Platform::get(&platforms);
platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
}
template<typename T>
void Foo<T>::bar() {
// Fails to compile: error: expected expression
//std::cout << devices[0].getInfo<CL_DEVICE_NAME>() << std::endl;
// Works
std::cout << devices[0].template getInfo<CL_DEVICE_NAME>() << std::endl;
// Also works
cl::Device &mydevice = devices[0];
std::cout << mydevice.getInfo<CL_DEVICE_NAME>() << std::endl;
}
和源文件:
//test.cpp
#include "test.hpp"
int main() {
Foo<double> foo = Foo<double>();
foo.bar();
return 0;
}
使模板歧义不必要的参考有什么不同?我试图了解歧义在哪里。 (另外,我知道我没有在我的班级中使用模板化变量,这只是一个复制问题的最小案例。)
答案 0 :(得分:1)
首先,这只是模板代码中的典型问题。问题是因为在解析时getInfo
的本质是未知的(它是函数模板还是常规成员变量?)解析器不知道是否要解释{ {1}}小于或开始指定模板参数。
因此§14.2[temp.names] / 4 中的规则,其示例为:
<
现在,在你的情况下,这似乎有点傻我想,因为它是template<class T> void f(T* p) {
T* p1 = p->alloc<200>(); // ill-formed: < means less than
T* p2 = p->template alloc<200>(); // OK: < starts template argument list
T::adjust<100>(); // ill-formed: < means less than
T::template adjust<100>(); // OK: < starts template argument list
}
对吗?是的,在您的情况下 。但是:
Device
所以,是的,规则不尽可能精确。它可以进一步深入研究,并检查是否可以推断出实际类型......
...但是你是否意识到,在某些情况下(非依赖情况),允许你在template <typename T> struct Wrecker { using type = std::vector<Device>; };
template <> struct Wrecker<double> { using type = std::vector<Other>; };
template <typename T>
struct Foo {
using Devices = typename Wrecker<T>::type;
Devices devices;
void bar();
};
中放弃的简单事实已经需要一个最糟糕的编译器黑客攻击?传统的管道:标记化 - &gt;解析 - &gt;语义分析必须在C ++中完全扭曲,以便在解析阶段允许反馈语义分析,以自动消除template
模板调用的歧义。
就个人而言,我的建议是系统地授权foo<4>()
。这本可以省去很多麻烦。