В результате статической функции «Специализированный вложенный класс» возникает ошибка компилятора C3855 (MSVC9) - PullRequest
1 голос
/ 01 мая 2011

Это продолжение моего предыдущего вопроса .

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

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

#include <cstdlib>
#include <iostream>
using namespace std;

class NullType {};

template<class FooParam> struct Foo
{
    template<class BarParam> struct Bar
    {
        static bool Magic();
    };
};

template<class FooParam> 
template<class BarParam> 
bool Foo<FooParam>::Bar<BarParam>::Magic()
{
    return true;
}

int main()
{
    bool b = Foo<int>::Bar<int>::Magic();
    cout << b << " ";
    bool b2 = Foo<int>::Bar<NullType>::Magic();
    cout << b2 << " ";

}

Этот код компилируется и запускается, как и ожидалось.Вывод:

1 1

Теперь я хочу предоставить специализацию Bar::Magic для NullType и вернуть эту функцию false.Желаемый результат:

1 0

Итак, я попытался написать специализацию следующим образом:

template<class FooParam>
template<>
bool Foo<FooParam>::Bar<NullType>::Magic()
{
    return false;
} // COMPILER ERROR HERE C3855

Это определение появляется перед существующим определением для Foo::Bar::Magic().

Однако этот код приводит к ошибке компилятора:

1>.\main.cpp(20) : error C3855: 'Foo<FooParam>::Bar<BarParam>': template parameter 'BarParam' is incompatible with the declaration

... на закрывающей скобке, указанной выше.

Какой синтаксис можно использовать для обеспечения этой специализации?Я открыт для любых методов для достижения моей главной цели (возвращая false для NullType и true для всего остального), если:

  1. Внешние библиотеки не используются (нетBoost)
  2. Используется только соответствующий C ++
  3. Foo - шаблон класса, а Bar - либо вложенный шаблон класса, либо шаблон функции.Функция, которая возвращает false или true, должна быть специализированной или перегружаемой таким образом, чтобы при вызове кода для NullType возвращалось false, а все остальное возвращало true.

Я уточню требования при необходимости.

Ответы [ 3 ]

2 голосов
/ 02 мая 2011

Специализация вложенного класса / метода без специализации включающего его класса запрещена как C ++ 03, так и C ++ 11, как упомянуто в комментарии @Ise Wisteria.

Будет ли работать следующее решение, которое использует перегрузку для вас?

#include <cstdlib>
#include <iostream>
using namespace std;

class NullType {};

template<class FooParam> struct Foo
{
    template<class BarParam> static bool Magic(BarParam);
    static bool Magic(NullType);
};

template<class FooParam> 
template<class BarParam> 
bool Foo<FooParam>::Magic(BarParam)
{
    return true;
}

template<class FooParam> 
bool Foo<FooParam>::Magic(NullType)
{
    return false;
}

int main()
{
    bool b = Foo<int>::Magic(int());
    cout << b << " ";
    bool b2 = Foo<int>::Magic(NullType());
    cout << b2 << " ";
}
2 голосов
/ 02 мая 2011

Другой альтернативный вариант - использовать класс не вложенных признаков:

class NullType {};

template<class FooParam> struct Foo
{
    template<class BarParam> struct Bar
    {
        static bool Magic();
    };
};

template<class T> struct bool_trait
{
    static const bool value = true;
};

template<> struct bool_trait<NullType>
{
    static const bool value = false;
};

template<class FooParam> 
template<class BarParam> 
bool Foo<FooParam>::Bar<BarParam>::Magic()
{
    return bool_trait<BarParam>::value;
}
1 голос
/ 02 мая 2011

Быстрое решение состоит в том, чтобы использовать оператор typeid, который является стандартным C ++ (5.2.8).Таким образом, ваша функция Magic () будет выглядеть следующим образом:

template<class FooParam> 
template<class BarParam> 
bool Foo<FooParam>::Bar<BarParam>::Magic()
{
    if (typeid(BarParam) == typeid(NullType))
        return false;

    return true;
}

Насколько я понимаю, компиляторы имеют некоторую свободу в реальной реализации typeid и typeinfo, но оператор == гарантированно будет работать как вы 'Я ожидал этого.Предостережение заключается в том, что некоторые компиляторы, по-видимому, по умолчанию не поддерживают информацию о типах во время выполнения для повышения производительности;у большинства должен быть флаг, чтобы включить его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...