Error explicit specialization in non namespace scope

Специализация внутренних шаблонных классов Сломал мозг уже. капец. В VC2008 все хорошо, в g++4.4.1 дохнем 🙁 На строчку template пишет «error: explicit specialization in non-namespace scope ‘struct External ’ « «Help me, pliz, pliz, pliiiz » (c) Битлы 🙂 MATov > Сломал мозг уже. капец. asm О первом предложеном способе: конечно можно вынести наружу, […]

Содержание

  1. Специализация внутренних шаблонных классов
  2. Explicit (full) template specialization
  3. Contents
  4. [edit] Syntax
  5. [edit] In detail
  6. [edit] Explicit specializations of function templates
  7. [edit] Members of specializations
  8. [edit] Defect reports
  9. Специализация внутренних шаблонных классов
  10. explicit specialization in non-namespace scope мать его! 🙁
  11. Re: explicit specialization in non-namespace scope мать его! 🙁
  12. Re: explicit specialization in non-namespace scope мать его! 🙁
  13. Re: explicit specialization in non-namespace scope мать его! 🙁
  14. Explicit (full) template specialization
  15. Contents
  16. [edit] Syntax
  17. [edit] In detail
  18. [edit] Explicit specializations of function templates
  19. [edit] Members of specializations
  20. [edit] Defect reports

Специализация внутренних шаблонных классов

Сломал мозг уже. капец.

В VC2008 все хорошо, в g++4.4.1 дохнем 🙁
На строчку template<> пишет «error: explicit specialization in non-namespace scope ‘struct External ’ «

«Help me, pliz, pliz, pliiiz » (c) Битлы 🙂

MATov
> Сломал мозг уже. капец.

asm
О первом предложеном способе:
конечно можно вынести наружу, но к сожалению код не мой, я его только правлю, а там такого очень много.

О втором:
Скомпилилось. Может кто-нибудь объяснить в чем дело?

частичная специализация идет, а полная нет..ну не дурдом ли. 🙁

Мона так, для удобства:

Но это не решает проблемы, кода такого не мало. Может флаг компилятора какой есть?

MATov
> Может флаг компилятора какой есть?
Типа, «—компилять-невалидный-код» ?
gcc корректно отказал в компиляции. То же скажет comeau.

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

MATov
> что ж в нем невалидного-то?
Не уверен в деталях, но суть в исторически сложившейся интерпретации стандарта.
Смотри пункт 14.7.3.2.
14.7.3(2): «An explicit specialization shall be declared in the
namespace of which the template is a member, or, for member templates,
in the namespace of which the enclosing class or enclosing class
template is a member. [. ]»

т.е. для шаблонов-членов специализация должна быть описана в том неймспейсе, где описан родительский класс.

Источник

Explicit (full) template specialization

Compiler support
Freestanding and hosted
Language
Standard library
Standard library headers
Named requirements
Feature test macros (C++20)
Language support library
Concepts library (C++20)
Metaprogramming library (C++11)
Diagnostics library
General utilities library
Strings library
Containers library
Iterators library
Ranges library (C++20)
Algorithms library
Numerics library
Localizations library
Input/output library
Filesystem library (C++17)
Regular expressions library (C++11)
Concurrency support library (C++11)
Technical specifications
Symbols index
External libraries

Flow control Conditional execution statements Functions Function declaration Lambda function expression inline specifier Dynamic exception specifications (until C++20) noexcept specifier (C++11) Exceptions Alternative representations Literals Boolean — Integer — Floating-point Character — String —

nullptr

(C++11) User-defined (C++11) Utilities Attributes (C++11) Types typedef declaration Type alias declaration (C++11) Casts Implicit conversions — Explicit conversions

static_cast

dynamic_cast const_cast

reinterpret_cast

Memory allocation Class-specific function properties

Template specialization
Parameter packs (C++11)
Parameters and arguments
Class templates
Function templates
Class member templates
Variable templates (C++14)
Template argument deduction
Class template argument deduction (C++17)
Explicit (full) specialization
Partial specialization
Dependent names
Parameter packs (C++11)
sizeof. (C++11)
Fold-expressions (C++17)
SFINAE
Constraints and concepts (C++20)
Requires expression (C++20)

Allows customizing the template code for a given set of template arguments.

Contents

[edit] Syntax

Any of the following can be fully specialized:

[edit] In detail

Explicit specialization may be declared in any scope where its primary template may be defined (which may be different from the scope where the primary template is defined; such as with out-of-class specialization of a member template) . Explicit specialization has to appear after the non-specialized template declaration.

Specialization must be declared before the first use that would cause implicit instantiation, in every translation unit where such use occurs:

A template specialization that was declared but not defined can be used just like any other incomplete type (e.g. pointers and references to it may be used):

[edit] Explicit specializations of function templates

When specializing a function template, its template arguments can be omitted if template argument deduction can provide them from the function arguments:

A function with the same name and the same argument list as a specialization is not a specialization (see template overloading in function template)

An explicit specialization of a function template is inline /constexpr (since C++11) /immediate (since C++20) only if it is declared with the corresponding specifier (or defined as deleted) (since C++11) , it does not matter if the primary template is declared with that specifier. Similarly, attributes appearing in the declaration of a template have no effect on an explicit specialization of that template: (since C++11)

Default function arguments cannot be specified in explicit specializations of function templates, member function templates, and member functions of class templates when the class is implicitly instantiated.

An explicit specialization cannot be a friend declaration.

This section is incomplete
Reason: review the exception specification requirement across different C++ versions

[edit] Members of specializations

When defining a member of an explicitly specialized class template outside the body of the class, the syntax template <> is not used, except if it’s a member of an explicitly specialized member class template, which is specialized as a class template, because otherwise, the syntax would require such definition to begin with template parameters > required by the nested template

An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. These definitions must use braces for default initialization:

A member or a member template of a class template may be explicitly specialized for a given implicit instantiation of the class template, even if the member or member template is defined in the class template definition.

Member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, there’s a template <> for every enclosing class template that is explicitly specialized.

In such a nested declaration, some of the levels may remain unspecialized (except that it can’t specialize a class member template if its enclosing class is unspecialized). For each of those levels, the declaration needs template arguments > , because such specializations are themselves templates:

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

Источник

Специализация внутренних шаблонных классов

Сломал мозг уже. капец.

В VC2008 все хорошо, в g++4.4.1 дохнем 🙁
На строчку template<> пишет «error: explicit specialization in non-namespace scope ‘struct External ’ «

«Help me, pliz, pliz, pliiiz » (c) Битлы 🙂

MATov
> Сломал мозг уже. капец.

asm
О первом предложеном способе:
конечно можно вынести наружу, но к сожалению код не мой, я его только правлю, а там такого очень много.

О втором:
Скомпилилось. Может кто-нибудь объяснить в чем дело?

частичная специализация идет, а полная нет..ну не дурдом ли. 🙁

Мона так, для удобства:

Но это не решает проблемы, кода такого не мало. Может флаг компилятора какой есть?

MATov
> Может флаг компилятора какой есть?
Типа, «—компилять-невалидный-код» ?
gcc корректно отказал в компиляции. То же скажет comeau.

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

MATov
> что ж в нем невалидного-то?
Не уверен в деталях, но суть в исторически сложившейся интерпретации стандарта.
Смотри пункт 14.7.3.2.
14.7.3(2): «An explicit specialization shall be declared in the
namespace of which the template is a member, or, for member templates,
in the namespace of which the enclosing class or enclosing class
template is a member. [. ]»

т.е. для шаблонов-членов специализация должна быть описана в том неймспейсе, где описан родительский класс.

Источник

explicit specialization in non-namespace scope мать его! 🙁

Млин, стоит задача переписать софт с виндовса в linux. Понятно дело, в коде куча расширений от мелкософтоского компилятора с++, одно из них — объявление внутри класса шаблонного класса с последующей специализацией этого класса внутри объявления внешнего класса. gcc не проглатывает это, не по стандарту это. Млин, но если подумать, вполне удобное расширение. Читаю в инете, какие приемы используют разработчики, чтобы это обойти, а другие их ругают, типа такое расширение противоречит всей концепции шаблонов, типа это надругательство. Чем он противоричит? Чем он плох в с++?

Re: explicit specialization in non-namespace scope мать его! 🙁

Используй MSVC; перепеши код на стандартный; добавь такое расширение в GCC — у тебя огромный выбор!

Re: explicit specialization in non-namespace scope мать его! 🙁

Да, кстати — очень плохо, что ты не удосужил себя написать пример, и объяснить/проверить, почему нельзя сделать специализацию этого класса снаружи объявления внешнего класса — какие религиозные взгляды тебе мешают?

Может, MSVC просто решили для себя именно так проблему оптимизации — в других компиляторах такое просто нафиг никому не нужно, не?

Re: explicit specialization in non-namespace scope мать его! 🙁

и компилятор похоже у вас msvc 2005, 2008 вроде как такое не должен проглатывать

Источник

Explicit (full) template specialization

Compiler support
Freestanding and hosted
Language
Standard library
Standard library headers
Named requirements
Feature test macros (C++20)
Language support library
Concepts library (C++20)
Metaprogramming library (C++11)
Diagnostics library
General utilities library
Strings library
Containers library
Iterators library
Ranges library (C++20)
Algorithms library
Numerics library
Localizations library
Input/output library
Filesystem library (C++17)
Regular expressions library (C++11)
Concurrency support library (C++11)
Technical specifications
Symbols index
External libraries

Flow control Conditional execution statements Functions Function declaration Lambda function expression inline specifier Dynamic exception specifications (until C++20) noexcept specifier (C++11) Exceptions Alternative representations Literals Boolean — Integer — Floating-point Character — String —

nullptr

(C++11) User-defined (C++11) Utilities Attributes (C++11) Types typedef declaration Type alias declaration (C++11) Casts Implicit conversions — Explicit conversions

static_cast

dynamic_cast const_cast

reinterpret_cast

Memory allocation Class-specific function properties

Template specialization
Parameter packs (C++11)
Parameters and arguments
Class templates
Function templates
Class member templates
Variable templates (C++14)
Template argument deduction
Class template argument deduction (C++17)
Explicit (full) specialization
Partial specialization
Dependent names
Parameter packs (C++11)
sizeof. (C++11)
Fold-expressions (C++17)
SFINAE
Constraints and concepts (C++20)
Requires expression (C++20)

Allows customizing the template code for a given set of template arguments.

Contents

[edit] Syntax

Any of the following can be fully specialized:

[edit] In detail

Explicit specialization may be declared in any scope where its primary template may be defined (which may be different from the scope where the primary template is defined; such as with out-of-class specialization of a member template) . Explicit specialization has to appear after the non-specialized template declaration.

Specialization must be declared before the first use that would cause implicit instantiation, in every translation unit where such use occurs:

A template specialization that was declared but not defined can be used just like any other incomplete type (e.g. pointers and references to it may be used):

[edit] Explicit specializations of function templates

When specializing a function template, its template arguments can be omitted if template argument deduction can provide them from the function arguments:

A function with the same name and the same argument list as a specialization is not a specialization (see template overloading in function template)

An explicit specialization of a function template is inline /constexpr (since C++11) /immediate (since C++20) only if it is declared with the corresponding specifier (or defined as deleted) (since C++11) , it does not matter if the primary template is declared with that specifier. Similarly, attributes appearing in the declaration of a template have no effect on an explicit specialization of that template: (since C++11)

Default function arguments cannot be specified in explicit specializations of function templates, member function templates, and member functions of class templates when the class is implicitly instantiated.

An explicit specialization cannot be a friend declaration.

This section is incomplete
Reason: review the exception specification requirement across different C++ versions

[edit] Members of specializations

When defining a member of an explicitly specialized class template outside the body of the class, the syntax template <> is not used, except if it’s a member of an explicitly specialized member class template, which is specialized as a class template, because otherwise, the syntax would require such definition to begin with template parameters > required by the nested template

An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. These definitions must use braces for default initialization:

A member or a member template of a class template may be explicitly specialized for a given implicit instantiation of the class template, even if the member or member template is defined in the class template definition.

Member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, there’s a template <> for every enclosing class template that is explicitly specialized.

In such a nested declaration, some of the levels may remain unspecialized (except that it can’t specialize a class member template if its enclosing class is unspecialized). For each of those levels, the declaration needs template arguments > , because such specializations are themselves templates:

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

Источник

  • Forum
  • General C++ Programming
  • Template specialization in non-namespace

Template specialization in non-namespace scope

Hi.

Look at this piece of code. (compiles on MSVC++, doesn’t compile on gcc and clang)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

using namespace std;

template<bool CONDITION, typename THEN, typename ELSE>
struct IF
{
    template<bool C>
    struct selector { using selected = THEN; };

    template<>
    struct selector<false> { using selected = ELSE; };

    using result = typename selector<CONDITION>::selected;
};

It says: «error: explicit specialization of ‘selector’ in class scope«

Reading around on the internet, it turned out I need to export the struct specialization outside the struct(first question: WHY???)

So I tried:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

using namespace std;

template<bool CONDITION, typename THEN, typename ELSE>
struct IF
{
     template<bool C>
     struct selector { using selected = THEN; };

//      template<>
//	struct selector<false> { using selected = ELSE; };

     using result = typename selector<CONDITION>::selected;
};

// SPECIALIZATION OUTSIDE THE CLASS!
template<>
struct IF::selector<false> { using selected = ELSE; };

The problem now is that it says I need to specify template arguments for IF, on line

 
struct IF<...here...>::selector<false> { using selected = ELSE; };

What do I write there? How do I go on at this point?

Last edited on

The C++ standard does not allow explicit specialization of a member of a class at class scope.

A canonical work-around to allow what in effect would behave like an explicit specialization inside the class is to use an extra unused template parameter with a default value:

1
2
3
4
5
6
7
8
9
10
11
template<bool CONDITION, typename THEN, typename ELSE>
struct IF
{
    template< bool C, typename fake = void >
    struct selector { using selected = THEN; };

    template< typename fake >
    struct selector<false,fake> { using selected = ELSE; };

    using result = typename selector<CONDITION>::selected;
};

Note: The standard library has

std::conditional<>

http://en.cppreference.com/w/cpp/types/conditional

Note: The standard library has std::conditional<>

I know about std::conditional<>, otherwise I couldn’t have ever imagined to do something similar ^^

The C++ standard does not allow explicit specialization of a member of a class at class scope.

Seems a pretty strange decision. Who knows… they must have their reasons…

What is stranger is that MSVC++ compiles fine… should I be worried?

Last edited on

> Seems a pretty strange decision. Who knows… they must have their reasons…

See: http://www.cplusplus.com/forum/general/58906/#msg318049

> What is stranger is that MSVC++ compiles fine… should I be worried?

No. For this, the Microsoft compilers are known to be non-conforming.
(Not sure if they fixed it in the recent Update 3.)

Topic archived. No new replies allowed.

Перенос предложения: голоса +13, -0
Автор идеи: Amomum

Сейчас этого делать нельзя, хотя в некоторых компиляторах можно (и никто не умирает). Причем частичная специализация почему-то разрешена.
Считаю, что никакого смысла в этом нет, обходные пути более многословны и уродливы.

Сейчас подобный код не компилируется с не очень внятной ошибкой:

class A
{
    private:

    template< typename T>
    class Inner
    {
        T value;
    };

    template<>
    class Inner<int>
    {
        int value;
    };
};
error: "explicit specialization in non-namespace scope 'class A'"

Простое решение — сделать специализацию частичной, добавив фейковый параметр Dummy:

class A
{
    private:

    template< typename T, typename Dummy = void>
    class Inner
    {
        T value;
    };

    template< typename Dummy>
    class Inner< int, Dummy >
    {
        int value;
    };
};

Однако такой код длиннее и менее понятен. К тому же, частичная специализация невозможна для шаблонных методов, которые страдают от той же проблемы.
Следует так же отметить, что некоторые компиляторы (в частности, MSVC) компилируют первый сниппет вопреки стандарту — и вроде как полет нормальный.

Причины, по которым стандарт это запрещает, неясны.

Предлагаю разрешить.

Изучаю шаблоны и не могу нормально скомпилировать код.
Версия компилятора — g++ (Debian 10.2.1-6) 10.2.1 20210110

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
 
template<typename T>
class A{
public:
    A(){}
    ~A(){}
    
    template<>
    void set_data<int>(int data){
        this->data = data;
    }
    
    template<>
    void set_data<double>(double data){
        this->data = data;
    }
    
private:
    T data;
}
 
int main(){
    A<int> a1;
    a1.set_data(10);
    
    A<double> a2;
    a2.set_data(3.1);
    return 0;
}

Проблема имеено с template<>
Если скомпилировать с -std=c++11, то выдает больше ошибок, чем с -std=c++20

c++11:

Кликните здесь для просмотра всего текста

template.cpp:9:11: error: explicit specialization in non-namespace scope ‘class A<T>’
9 | template<>
| ^
template.cpp:10:7: error: variable or field ‘set_data’ declared void
10 | void set_data<int>(int data){
| ^~~~~~~~
template.cpp:10:7: error: expected ‘;’ at end of member declaration
10 | void set_data<int>(int data){
| ^~~~~~~~
| ;
template.cpp:10:15: error: expected unqualified-id before ‘<’ token
10 | void set_data<int>(int data){
| ^
template.cpp:14:11: error: explicit specialization in non-namespace scope ‘class A<T>’
14 | template<>
| ^
template.cpp:15:7: error: variable or field ‘set_data’ declared void
15 | void set_data<double>(double data){
| ^~~~~~~~
template.cpp:15:7: error: expected ‘;’ at end of member declaration
15 | void set_data<double>(double data){
| ^~~~~~~~
| ;
template.cpp:15:15: error: expected unqualified-id before ‘<’ token
15 | void set_data<double>(double data){
| ^
template.cpp:21:2: error: expected ‘;’ after class definition
21 | }
| ^
| ;
template.cpp: In function ‘int main()’:
template.cpp:25:5: error: ‘class A<int>’ has no member named ‘set_data’
25 | a1.set_data(10);
| ^~~~~~~~
template.cpp:28:5: error: ‘class A<double>’ has no member named ‘set_data’
28 | a2.set_data(3.1);

c++20:

Кликните здесь для просмотра всего текста

template.cpp:9:11: error: explicit specialization in non-namespace scope ‘class A<T>’
9 | template<>
| ^
template.cpp:10:7: error: template-id ‘set_data<int>’ in declaration of primary template
10 | void set_data<int>(int data){
| ^~~~~~~~~~~~~
template.cpp:14:11: error: explicit specialization in non-namespace scope ‘class A<T>’
14 | template<>
| ^
template.cpp:15:7: error: template-id ‘set_data<double>’ in declaration of primary template
15 | void set_data<double>(double data){
| ^~~~~~~~~~~~~~~~
template.cpp:21:2: error: expected ‘;’ after class definition
21 | }
| ^
| ;

Добавлено через 2 минуты
PS Только сейчас заметил, что после класса не поставил ; (в строке 21), но это ничего не меняет.

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь


Description


songyuanyao



2018-04-08 01:01:22 UTC

According to CWG 727, the following code should be accepted; i.e. full specialization may be declared inside class definition.

struct A {
  template<class T> struct B;
  template <> struct B<int*> { };
};

And per [temp.expl.spec] paragraph 2,

An explicit specialization may be declared in any scope in which the corresponding primary template may be defined ([namespace.memdef], [class.mem], [temp.mem]).


Comment 1


songyuanyao



2018-04-08 01:07:40 UTC

The error message for the code (from gcc8.0.1):

error: explicit specialization in non-namespace scope


Comment 3


Jonathan Wakely



2019-09-10 07:40:10 UTC

https://wg21.link/cwg727

N.B. this is a C++17 feature that does not seem to have been approved as a DR, but Clang supports it in all language modes.

Carlo, as an aside, your allocator fails to meet the allocator requirements. Rebinding must be reversible, so A<T>::rebind<U>::other::rebind<T>::other must give you back A<T>.


Comment 4


Marek Polacek



2020-05-16 14:44:10 UTC

*** Bug 95160 has been marked as a duplicate of this bug. ***


Comment 5


Ruslan Altynbaev



2020-05-22 10:00:55 UTC

(In reply to Jonathan Wakely from comment #3)
> https://wg21.link/cwg727
> 
> N.B. this is a C++17 feature that does not seem to have been approved as a
> DR, but Clang supports it in all language modes.
> 
CWG 727 says "Adopted at the February/March, 2017 meeting", and [temp.class.spec]/5 in ISO/IEC 14882:2017(E) is reflecting the new wording. So this is in C++17. The defect is on GCC side.


Comment 6


Jonathan Wakely



2020-05-22 10:35:34 UTC

(In reply to Rustam Abdullaev from comment #5)
> (In reply to Jonathan Wakely from comment #3)
> > https://wg21.link/cwg727
> > 
> > N.B. this is a C++17 feature that does not seem to have been approved as a
> > DR, but Clang supports it in all language modes.
> > 
> CWG 727 says "Adopted at the February/March, 2017 meeting", and
> [temp.class.spec]/5 in ISO/IEC 14882:2017(E) is reflecting the new wording.
> So this is in C++17. The defect is on GCC side.

Yes. That's what I said.

But it's not a DR, so it only applies to C++17 and not C++14 or older standards.


Comment 8


Marek Polacek



2020-07-16 13:59:43 UTC

*** Bug 96219 has been marked as a duplicate of this bug. ***


Comment 9


S. Davis Herring



2020-07-31 01:12:46 UTC

> But it's not a DR, so it only applies to C++17 and not C++14 or older
> standards.

Isn't it?  Its motion does say "accept as Defect Reports".


Comment 10


Jonathan Wakely



2020-07-31 11:56:20 UTC

(In reply to S. Davis Herring from comment #9)
> > But it's not a DR, so it only applies to C++17 and not C++14 or older
> > standards.
> 
> Isn't it?  Its motion does say "accept as Defect Reports".

I'm only going by what the issues list says. If that's wrong we should ask Mike to update it.


Comment 11


Jonathan Wakely



2020-08-06 19:16:15 UTC

(In reply to Jonathan Wakely from comment #10)
> I'm only going by what the issues list says. If that's wrong we should ask
> Mike to update it.

FTAOD, what I meant was that I *was* only going by what the issues list says when I claimed it's not a DR. I didn't mean to imply that I *will* only go by what the issues list says in all cases.

So when GCC implements it, it should be for every mode.


Comment 13


Jason Merrill



2020-12-09 14:36:23 UTC

I vaguely remember us supporting this in the distant past, but removing that support to be conforming.

Ah, yes, in 1998: r0-18485


Comment 14


Andrew Pinski



2021-08-10 15:27:46 UTC

*** Bug 101848 has been marked as a duplicate of this bug. ***


Comment 15


Andrew Pinski



2021-08-10 15:29:37 UTC

*** Bug 93992 has been marked as a duplicate of this bug. ***


Comment 16


Patrick Palka



2021-11-14 15:14:15 UTC

*** Bug 103232 has been marked as a duplicate of this bug. ***


Comment 17


Patrick Palka



2022-03-29 15:39:39 UTC

This won't be implemented in time for GCC 12, sadly.

FWIW a class-scope explicit specialization should in most cases be equivalent to an appropriately constrained partial specialization.  So as a workaround, instead of e.g.:

struct A {
  template<class T>
  struct B;

  template<>
  struct B<int> { }; // unsupported class-scope explicit specialization
};

in C++20 one can do:

struct A {
  template<class T>
  struct B;

  template<std::same_as<int> T>
  struct B<T> { };
};

or in C++17:

struct A {
  template<class T, class = void>
  struct B;

  template<class T>
  struct B<T, std::enable_if_t<std::is_same_v<int, T>>> { };
};

Hey guys,

the following code:

http://code.google.c…SBPropertySet.h

/*
The zlib/libpng License

Copyright (c) 2009-2010 Martin Preisler

This software is provided 'as-is', without any express or implied warranty. In no event will
the authors be held liable for any damages arising from the use of this software.

Permission is granted to anyone to use this software for any purpose, including commercial
applications, and to alter it and redistribute it freely, subject to the following
restrictions:

1. The origin of this software must not be misrepresented; you must not claim that
you wrote the original software. If you use this software in a product,
an acknowledgment in the product documentation would be appreciated but is
not required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.

3. This notice may not be removed or altered from any source distribution.
*/

#ifndef __OISB_PROPERTY_SET_H__
#define __OISB_PROPERTY_SET_H__

#include "OISBGlobal.h"
#include "OISBString.h"
#include

namespace OISB
{
/**
* @brief base abstract class for all classes allowing property set/get
*/
class _OISBExport PropertySet
{
public:
/**
* @brief destructor
*/
virtual ~PropertySet();

typedef std::vector PropertyList;
virtual void listProperties(PropertyList& list);

/**
* @brief sets property of given name to given value
*/
template
inline void setProperty(const String& name, const T& value)
{
impl_setProperty(name, toString(value));
}

/// @copydoc PropertySet::setProperty
template<>
inline void setProperty(const String& name, const String& value)
{
impl_setProperty(name, value);
}

/**
* @brief gets property of given name and the result is returned as given type
*/
template
inline typename T getProperty(const String& name) const
{
return fromString(impl_getProperty(name));
}

/// @copydoc PropertySet::getProperty
template<>
inline String getProperty(const String& name) const
{
return impl_getProperty(name);
}

/// coverts given type to string, idea from boost::lexical_cast
template
inline static String toString(const T& value)
{
std::ostringstream sstr;
sstr << value;

return sstr.str();
}

/// converts given string to type, idea from boost::lexical_cast
template
inline static T fromString(const String& value)
{
T ret;

std::istringstream sstr(value);
sstr >> ret;

return ret;
}

protected:
/**
* @brief implementation of property set
*/
virtual void impl_setProperty(const String& name, const String& value);

/**
* @brief implementation of property get
*/
virtual String impl_getProperty(const String& name) const;
};
}

#endif

(You can see the line numbers if you follow the link)

gives the following errors when compiled with g++ (Debian 4.3.2-1.1) 4.3.2:

oisb/include/OISBPropertySet.h:57: error: explicit specialization in non-namespace scope ‘class OISB::PropertySet’
oisb/include/OISBPropertySet.h:67: error: expected nested-name-specifier before ‘T’
oisb/include/OISBPropertySet.h:67: error: too many template-parameter-lists
oisb/include/OISBPropertySet.h:73: error: explicit specialization in non-namespace scope ‘class OISB::PropertySet’
oisb/include/OISBPropertySet.h:81: error: too many template-parameter-lists
oisb/include/OISBPropertySet.h:91: error: too many template-parameter-lists[/quote]

It appears that Visual C++ thinks that code is OK. It would be great if someone could explain why these errors happen and how the code should be changed to make it work.

I’m not the author of the code — I’m a user of the library and just trying to help the author to get it fixed so that it can be used on Linux too.

Я знаю, что есть много сообщений о «Явная специализация в области, не связанной с пространством имен«; я уже читал большинство из них, но (если только я плохо понял ответы) они не отвечают на этот конкретный вопрос. На самом деле, я нашел обходной путь в своей программе, но мне интересно узнать «реальное решение» этой проблемы, если оно есть.

Проблема

Пожалуйста, потерпите меня, это трудно выразить словами. У меня есть класс шаблона A<typename T, unsigned n>. Я хочу определить средство проверки типов как внутреннюю структуру шаблона. is_A<typename U> который проверяет, если U это какой-то A. Эта структура наследуется от std::false_type как есть, и я специализируюсь на том, чтобы вывести его из std::true_type для типов шаблонов A<U,n>.

Почему я хочу это сделать? Потому что я хочу определить метод шаблона A::method<U> который ведет себя по-разному, когда U это какой-то A или иным образом.

Что сработало

  1. Вводя неспециализированное определение is_a<U> до объявления A. И поставить потом специализированную версию с 2 аргументами шаблона вместо 1; ie template <> template <typename T, unsigned n> struct is_A< A<T,n> > : std::true_type {};. Почему бы и нет, но мне не очень нравится добавлять аргумент шаблона и взрывать определение is_A тоже не очень красиво…
  2. Удаление is_A и используя другую проверку типов для method который характеризует именно тот тип, который я ожидаю (ie, подход белого списка вместо черного списка).

Есть ли другой способ, кроме этих обходных путей, который позволяет написать что-то похожее на следующий заголовок?

Код

Вот самый маленький заголовок, который я мог бы написать, чтобы воспроизвести ошибку:

#ifndef __EXAMPLE__
#define __EXAMPLE__

#include <type_traits>

namespace name
{


template <typename T, unsigned n>
class A
{
public:

    /**
     * Type checkers
     */
    template <typename U>
    struct is_A : public std::false_type {};

    template <> template <typename U>
    struct is_A< A<U,n> > : public std::true_type {};

    /**
     * Specialized method
     */

     // Version taking input of type A<U,n>
    template <typename U>
    void method( const A<U,n>& other ) {}

    // Version taking inputs of other types
    template <typename U,
    typename = typename std::enable_if< !is_A<U>::value >::type >
    void method( const U& x ) {}
};


}

#endif

Вот ошибка, которую я получаю, когда компилирую файл cpp, включая этот заголовок:

.h:21:12: error: explicit specialization in non-namespace scope 'class name::A<T, n>'
.h:30:7: error: too many template-parameter-lists
.h:35:7: error: too many template-parameter-lists

Понравилась статья? Поделить с друзьями:
  • Error expected unqualified id before token ошибка
  • Error expected unqualified id before switch
  • Error expected unqualified id before string constant extern c
  • Error expected unqualified id before return
  • Error expected unqualified id before public