【问题标题】:template template parameters and clang模板模板参数和clang
【发布时间】:2013-11-17 05:02:53
【问题描述】:

我在使用模板模板参数和 clang 时遇到了问题(可能是我的问题)。以下玩具示例在 g++ 4.7.0 下编译和运行,而不是 clang++ 3.0(基于 LLVM 3.0),两者都是 ubuntu 12.04。

玩具示例(test_1.cpp):

#include <iostream>                                                                                 
#include <memory>                                                                                   

struct AFn                                                                                          
{                                                                                                   
   void operator()()                                                                                
     {                                                                                              
    ; // do something                                                                               
     }                                                                                              
};                                                                                                  

template<typename T>                                                                                
  struct impl                                                                                       
{                                                                                                   
   T *backpointer_;                                                                                 
};                                                                                                  

template<typename S, template <typename> class T>                                                   
  struct implT                                                                                      
{                                                                                                   
   T<S> *backpointer_;                                                                              
};                                                                                                  

template<typename>                                                                                  
  class AClass;                                                                                     

template<>                                                                                          
  struct implT<AFn, AClass>                                                                         
{                                                                                                   
   implT(std::string message) :                                                                     
     message_(message)                                                                              
       {}                                                                                           

   void operator()()                                                                                
     {                                                                                              
    std::cout << " : " << message_ << std::endl;                                                    
     }                                                                                              

   std::string message_;                                                                            
};                                                                                                  


template<typename Fn>                                                                               
class AClass                                                                                        
{                                                                                                   
 private:                                                                                           
   std::shared_ptr<implT<Fn, AClass> > p_;                                                          
 public:                                                                                            
   AClass(std::string message) :                                                                    
     p_(std::make_shared<implT<Fn, AClass> >(message))                                              
       {}                                                                                           
   void call_me()             
     {                                                                                              
    p_->operator()();                                                                               
     }                                                                                              
};                                                                                                  


int main(int argc, char **argv)                                                                     
{                                                                                                   
   AClass<AFn> *A = new AClass<AFn>("AClass<AFn>");                                                 
   A->call_me();                                                                                    

   delete A;                                                                                        

   return 0;                                                                                        
}                                                                                           

叮当输出:

*****@ely:~$ clang++ -std=c++11 test_1.cpp -o test_1
test_1.cpp:47:30: error: template argument for template template parameter must be a class template or
      type alias template
   std::shared_ptr<implT<Fn, AClass> > p_;
                         ^
test_1.cpp:47:40: error: C++ requires a type specifier for all declarations
   std::shared_ptr<implT<Fn, AClass> > p_;
                                   ^~
test_1.cpp:50:36: error: template argument for template template parameter must be a class template or
  type alias template
 p_(std::make_shared<implT<Fn, AClass> >(message))
                               ^
3 errors generated.
                                                                                        I can't make sense of the first error. It compiles and runs fine with gcc/g++ 4.7.0. Any help would be appreciated.        

【问题讨论】:

    标签: c++ templates clang clang++


    【解决方案1】:

    如前所述,这是一个 Clang 错误。 AClass 有一个 injected-class-name,一个独特的语法结构,它既是 class-name 又是 template-name

    另一种解决方法是说AClass::template AClass。这避免了需要使用其封闭的命名空间来限定 AClass

    【讨论】:

    • +1 我确实有 clang 3.0,它的行为与您在使用第二个解决方法时所描述的完全一样。
    • 当我遇到同样的问题时,我尝试了这个解决方案。它解决了 Clang 的问题,但现在在 gcc 上中断了。
    • 不幸的是 AClass::template AClassnot standard, and clang 5 warns about it
    【解决方案2】:

    Clang 3.3 也发生了同样的事情。

    this SO question 中的解决方案或变通方法是在第 47 行和第 50 行将 AClass 替换为 ::AClass,然后它可以顺利编译。

    说实话模板模板参数让我头疼。引用的问题表明这是一个 Clang 错误,但我还不够专家能够说。

    【讨论】:

    • 这当然是一个错误。语言设计似乎跳过了所有类型的障碍,以确保名称必须是模板或非模板,但随后它使编译器惊讶于注入的类名同时两者。
    • 这是前面提到的 SO 的重复,尽管我没有使用 CRTP(虽然这里有一个递归模板)。我得到它来编译,但你提到的那个标准有点令人困惑 - 让我试着把我的头绕过去......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 2020-10-27
    • 1970-01-01
    相关资源
    最近更新 更多