2017-01-18 10 views
2

У меня есть следующий код, который отлично компилируется под в Visual Studio и г ++, но в Clang я получаю ошибку «Ошибка:„нс :: B“неполный типа»шаблона Clang неполного типа

Ах

#pragma once 
namespace ns 
{ 
    class B; 

    class A 
    { 
     friend class B; 
     class Inner 
     { 
     public: 
      int x; 
      Inner(int x) : x(x) {} 
     }; 
    public: 
     template<typename T> 
     T getB(int i) 
     { 
      B b = B(Inner(i)); 
      return T(b); 
     } 

    }; 
} 

Bh

#pragma once 
#include "A.h" 

namespace ns 
{ 
    class B 
    { 
     A::Inner i; 
    public: 
     B(A::Inner i) : i(i) 
     {} 

     operator int() const 
     { 
      return i.x; 
     } 
    }; 
} 

main.cpp

#include "A.h" 
#include "B.h" 

int main() 
{ 
    ns::A a; 
    return a.getB<int>(5); 
} 

С моей точки зрения код должен работать, потому что к моменту создания шаблона B завершается. Это верно? И если да, есть ли способ решить проблему в Clang?

+0

Unrelated примечание стороны: '#include "хиджры"' в main.cpp не имеет смысла. – SingerOfTheFall

+3

@SingerOfTheFall Хорошо и полезно неоднократно включать заголовки, но они должны включать в себя охранники, которые здесь не показаны. – Potatoswatter

+0

@Potatoswatter Правильно жаль, я пропустил их при копировании. –

ответ

4

Программа плохо сформирована, не требуется диагностика.

[temp.res]/8:

The program is ill-formed, no diagnostic required, if:

  • [...]
  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or
  • [...]
+1

... так что одно решение состоит только в том, чтобы только «forward» объявить 'A :: getB' в' A.h' и определить его в 'B.h'. – Potatoswatter

+0

@Potatoswatter потрясающий, спасибо много. У вас есть идеи, почему он будет работать в VS и g ++? –

+2

@MikeJones: Visual не выполняет проверку 2 пропусков для шаблона (что не соответствует стандарту), и поэтому не проверяет независимый код. Для g ++ (который выполняет проверку 2-х проходов), они упускают возможность диагностировать это. – Jarod42