为什么在这种情况下需要模板消除歧义?

时间:2014-03-21 18:15:27

标签: c++ templates opencl

我试图理解为什么我需要在某些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;
}

使模板歧义不必要的参考有什么不同?我试图了解歧义在哪里。 (另外,我知道我没有在我的班级中使用模板化变量,这只是一个复制问题的最小案例。)

1 个答案:

答案 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>()。这本可以省去很多麻烦。

相关问题