, Кроме того, «имя» зависит от компилятора и / или платформы. : /

равится давать полезные ошибки / сообщения, и я также хочу сделать это для моегоstatic_asserts. Проблема в том, что они зависят от параметров шаблона. Обычно эти параметры отображаются в пути или по другому из-за возникшей ошибки, но они либо неясны, либо не сгруппированы, поэтому имеют смысл. Пример:

template<class T>
struct fake_dependency{
  static bool const value = false;
};

template<class T, class Tag>
struct Foo{
  Foo(){}

  template<class OtherTag>
  Foo(Foo<T, OtherTag> const&){
    static_assert(fake_dependency<T>::value, "Cannot create Foo<T,Tag> from Foo<T,OtherTag>.");
  }
};

int main(){
    Foo<int, struct TagA> fA;
    Foo<int, struct TagB> fB(fA);
}

Выход на MSVC:

src\main.cpp(74): error C2338: Cannot create Foo<T,Tag> from Foo<T,OtherTag>.
          src\main.cpp(84) : see reference to function template instantiation 'Foo<T,Tag>::Foo<main::TagA>(const Foo<T,main::TagA> &)' being compiled
          with
          [
              T=int,
              Tag=main::TagB
          ]

Один тег упоминается в самом шаблоне функции, другой ниже - с шаблоном класса. Не так приятно Давайте посмотрим, чтоВыходы GCC:

prog.cpp: In constructor 'Foo<T, Tag>::Foo(const Foo<T, OtherTag>&) [with OtherTag = main()::TagA, T = int, Tag = main()::TagB]':
prog.cpp:18:32:   instantiated from here
prog.cpp:12:5: error: static assertion failed: "Cannot create Foo<T,Tag> from Foo<T,OtherTag>."

Намного лучше, но все же не совсем то, гдеstatic_assert является. А теперь представьте еще несколько параметров, или больше шаблонов, или оба.обломки

Один из способов обойти это - использовать промежуточную структуру, которая принимает оба тега в качестве параметров шаблона:

template<class Tag, class OtherTag>
struct static_Foo_assert{
    static_assert(fake_dependency<Tag>::value, "Cannot create Foo<T,Tag> from Foo<T,OtherTag>.");
};

template<class T, class Tag>
struct Foo{
  Foo(){}

  template<class OtherTag>
  Foo(Foo<T, OtherTag> const&){
      static_Foo_assert<Tag, OtherTag> x;
  }
};

Теперь давайте снова посмотрим на результат:

src\main.cpp(70): error C2338: Cannot create Foo<T,Tag> from Foo<T,OtherTag>.
          src\main.cpp(79) : see reference to class template instantiation 'static_Foo_assert<Tag,OtherTag>' being compiled
          with
          [
              Tag=main::TagB,
              OtherTag=main::TagA
          ]

Намного лучше! Вот чтоGCC говорит:

prog.cpp: In instantiation of 'static_Foo_assert<main()::TagB, main()::TagA>':
prog.cpp:17:40:   instantiated from 'Foo<T, Tag>::Foo(const Foo<T, OtherTag>&) [with OtherTag = main()::TagA, T = int, Tag = main()::TagB]'
prog.cpp:23:32:   instantiated from here
prog.cpp:8:5: error: static assertion failed: "Cannot create Foo<T,Tag> from Foo<T,OtherTag>."

Выглядит неплохо. Проблема: мне нужно создать такую ​​структуру для каждого шаблона, так как сообщение об ошибке вstatic_assert должен быть строковым литералом ...

Теперь, на мой вопрос: можем ли мы как-то включить имена типов непосредственно вstatic_assert? подобно

static_assert(..., "Cannot create Foo<" T "," Tag "> from Foo<" T "," OtherTag ">.");

Пример вывода:

Не может создатьFoo<int,main::TagA> изFoo<int,main::TagB>.

Или, если это недостижимо, можем ли мы как-то сделать сообщение об ошибке дополнительным параметром шаблона, чтобы сделать его проходимым?

Ответы на вопрос(5)

Ваш ответ на вопрос