LINUX.ORG.RU

C++ специализация шаблона для значения параметра шаблона своего типа

 , , ,


1

3

не могу понять, как сделать специализацию шаблонного метода нешаблонного класса (либо просто функции) по значению параметра шаблона своего типа?

пример:

enum class myType { FF, DD, GG }

template < myType >
void foo () {};

template <>
void foo < myType::DD > () {
...
}


так не получается — грит ошибка: идентификатор шаблона «getNumRemainedCards<lp::Board::boardState::RIVER>» для «constexpr int8_t lp::Deck::getNumRemainedCards( » не соответствует никакой декларации шаблона

★★

Ответ на: комментарий от slovazap

переместил специализации внутрь класса — получил больше ошибок на одну специализацию:

/home/safff/Projects/PokerCalc/./include/Deck.h:41:15: ошибка: явная специализация в не-namespace области «struct lp::Deck»
   41 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::TURN >() { return 44; }
      |               ^
/home/safff/Projects/PokerCalc/./include/Deck.h:41:81: ошибка: template-id ard::boardState::TURN>» в декларации первичного шаблона
   41 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::TURN >() { return 44; }
      |                                                                                 ^
/home/safff/Projects/PokerCalc/./include/Deck.h:41:34: ошибка: «constexpr int8_t lp::Deck::getNumRemainedCards()» cannot be overloaded with «constexpr int8_t lp::Deck::getNumRemainedCards()»
   41 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::TURN >() { return 44; }
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/safff/Projects/PokerCalc/./include/Deck.h:42:15: ошибка: явная специализация в не-namespace области «struct lp::Deck»
   42 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::RIVER >() { return 43; }
      |               ^
/home/safff/Projects/PokerCalc/./include/Deck.h:42:82: ошибка: template-id «getNumRemainedCards<lp::Board::boardState::RIVER>» в декларации первичного шаблона
   42 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::RIVER >() { return 43; }
      |                                                                                  ^
/home/safff/Projects/PokerCalc/./include/Deck.h:42:34: ошибка: «constexpr int8_t lp::Deck::getNumRemainedCards()» cannot be overloaded with «constexpr int8_t lp::Deck::getNumRemainedCards()»
   42 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::RIVER >() { return 43; }
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/safff/Projects/PokerCalc/./include/Deck.h:41:15: ошибка: явная специализация в не-namespace области «struct lp::Deck»
   41 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::TURN >() { return 44; }
      |               ^
/home/safff/Projects/PokerCalc/./include/Deck.h:41:81: ошибка: template-id «getNumRemainedCards<lp::Board::boardState::TURN>» в декларации первичного шаблона
   41 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::TURN >() { return 44; }
      |                                                                                 ^
/home/safff/Projects/PokerCalc/./include/Deck.h:41:34: ошибка: «constexpr int8_t lp::Deck::getNumRemainedCards()» cannot be overloaded with «constexpr int8_t lp::Deck::getNumRemainedCards()»
   41 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::TURN >() { return 44; }
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/safff/Projects/PokerCalc/./include/Deck.h:42:15: ошибка: явная специализация в не-namespace области «struct lp::Deck»
   42 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::RIVER >() { return 43; }
      |               ^
/home/safff/Projects/PokerCalc/./include/Deck.h:42:82: ошибка: template-id «getNumRemainedCards<lp::Board::boardState::RIVER>» в декларации первичного шаблона
   42 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::RIVER >() { return 43; }
      |                                                                                  ^
/home/safff/Projects/PokerCalc/./include/Deck.h:42:34: ошибка: «constexpr int8_t lp::Deck::getNumRemainedCards()» cannot be overloaded with «constexpr int8_t lp::Deck::getNumRemainedCards()»
   42 |     template <> constexpr int8_t getNumRemainedCards< Board::boardState::RIVER >() { return 43; }
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

safocl ★★ ()
Последнее исправление: safocl (всего исправлений: 3)

УМВР

#include <iostream>

enum class myType { FF, DD, GG };

template < myType >
void foo () {
    std::cout << "base" << std::endl;
}

template <>
void foo < myType::DD > () {
    std::cout << "specialized" << std::endl;
}

int main() {
    foo<myType::FF>();
    foo<myType::DD>();
    return 0;
}
$ /usr/bin/clang++ -Wall -Wextra -Werror -pedantic -std=c++17 1.cpp && ./a.out
base
specialized

Вероятно ошибка где-то в другом месте.

filosofia ()
Ответ на: комментарий от safocl

Реализовать стандарт C++ невозможно принципиально, т.к. в нём немало чисто логических противоречий или недоопределённостей.

А ты про какие-то баги…

anonymous ()
Ответ на: комментарий от Ower

Так тут же написано

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.

Т.е. данная функция не была одобрена.

rumgot ★★★★★ ()
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от rumgot

C++17 §17.6.5.6 (332)

A class template partial specialization may be declared in any scope in which the corresponding primary template may be defined (10.3.1.2, 12.2, 17.6.2). [ Example:

template<class T> 
struct A {
  struct C {
    template<class T2> struct B { };
    template<class T2> struct B<T2**> { }; // partial specialization #1
  };
};

Здесь указано, что он применен также к C++14, а clang поддерживает во всех режимах, на что и указывал тот комментатор.

Хотя,

that does not seem to have been approved as a DR

предполагает, что и для 14 не применено, но это сути не меняет.

Ower ()
Последнее исправление: Ower (всего исправлений: 1)
Ответ на: комментарий от rumgot

а зачем тут обычная, если надо что бы в компайл тайме делалась?
ваще в свете ентих событий сделал без специализаций шаблонов:

template < Board::boardState S > constexpr static int8_t getNumRemainedCards() {
    if constexpr ( S == Board::boardState::PREFLOP )
        return 48;
    else if constexpr ( S == Board::boardState::FLOP )
        return 45;
    else if constexpr ( S == Board::boardState::TURN )
        return 44;
    else if constexpr ( S == Board::boardState::RIVER )
        return 43;
}

вроде полный компайл тайм

safocl ★★ ()
Ответ на: комментарий от rumgot

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

safocl ★★ ()
Последнее исправление: safocl (всего исправлений: 1)
Ответ на: комментарий от safocl

ну при обработке обычного аргумента не гарантируется чо компилятор решит чо все доступно в компайл тайме и сделает констэкспрами..

Ты тему не переводи. Обычная функция не компайл тайме делается?

rumgot ★★★★★ ()
Ответ на: комментарий от rumgot

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

safocl ★★ ()
Последнее исправление: safocl (всего исправлений: 1)
Ответ на: комментарий от safocl

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

rumgot ★★★★★ ()
Ответ на: комментарий от rumgot

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

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

safocl ★★ ()
Последнее исправление: safocl (всего исправлений: 1)
Ответ на: комментарий от rumgot

Т.е. данная функция не была одобрена.

Что ты несёшь, какая нахуй функция?

DR это значит что баг стандарта признаётся дефектом в ранее выпущенных стандартах и фикс этого дефекта является неотъемлемой частью уже выпущенных стандартов, так что компиляторы должны следовать исправленному комитетом поведению во всех режимах.

У CWG727 статус «C++17», т.е. это изменение поведения которое применимо только для стандарта C++17, но не к ранее выпущенным стандартам.

anonymous ()