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

Rob*_*lck 5 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;

}
Run Code Online (Sandbox Code Playgroud)

和源文件:

//test.cpp
#include "test.hpp"

int main() {
    Foo<double> foo = Foo<double>();    
    foo.bar();    
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

Mat*_* M. 1

首先,这只是模板代码中的一个典型问题。问题在于,因为在解析时,的性质getInfo是未知的(它是函数模板还是常规成员变量?),解析器不知道是否将其解释<为小于或指定模板参数的开始。

\n\n

因此\xc2\xa714.2 [temp.names]/4中的规则,其示例是:

\n\n
template<class T> void f(T* p) {\n    T* p1 = p->alloc<200>();          // ill-formed: < means less than\n    T* p2 = p->template alloc<200>(); // OK: < starts template argument list\n    T::adjust<100>();                 // ill-formed: < means less than\n    T::template adjust<100>();        // OK: < starts template argument list\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,就你的情况而言,我认为这似乎有点愚蠢,因为这是对的Device?是的,就你而言。但什么是:

\n\n
template <typename T> struct Wrecker { using type = std::vector<Device>; };\ntemplate <> struct Wrecker<double> { using type = std::vector<Other>; };\n\ntemplate <typename T>\nstruct Foo {\n    using Devices = typename Wrecker<T>::type;\n    Devices devices;\n\n    void bar();\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以,是的,该规则并不它应有的那么精确。它可以进一步深入研究冲突并检查是否可以推断出实际类型......

\n\n

...但是您是否意识到,事实上,允许您template在某些情况下(非依赖情况)进行省略的简单事实已经需要有史以来最糟糕的编译器黑客之一?传统的管道:标记化 -> 解析 -> 语义分析必须在 C++ 中完全扭曲,以允许在解析阶段提供语义分析反馈foo<4>(),从而自动消除模板调用的歧义。

\n\n

就我个人而言,我的建议是template系统地强制执行。本来可以省去很多麻烦。

\n