C ++ шаблон специализированных получателей

В настоящее время я пишу программу, работающую с NURBS surfacesгде вы можете выполнять алгоритмы в двух направлениях (U а также V). Чтобы избежать дублирования кода, я пытался использовать шаблоны, но я ни в коем случае не имел опыта их использования. Вот небольшой пример того, что я хотел бы сделать:

#include <iostream>

enum class Dir {
U, V
};

struct Foo {

unsigned cu, cv;

Foo(unsigned cu, unsigned cv) : cu(cu), cv(cv) {};

template<Dir>
const Dir otherDir();

template<>
const Dir otherDir<Dir::V>() {
return Dir::U;
}

template<>
const Dir otherDir<Dir::U>() {
return Dir::V;
}

template<Dir>
unsigned count();

template<>
unsigned count<Dir::U>() {
return cu;
}

template<>
unsigned count<Dir::V>() {
return cv;
}

template<Dir d>
unsigned totalCount() {
auto c = count<d>();
auto cOther = count<otherDir<d>()>();
return c * cOther;
}

};

int main() {
Foo f(3,2);
std::cout << (f.count<Dir::U>() == 3) << std::endl;
std::cout << (f.otherDir<Dir::U>() == Dir::V) << std::endl;
std::cout << f.totalCount<Dir::U>() << std::endl;
}

но это не компилируется из-за последней строки в main (VS2015, но я не думаю, что это ошибка компилятора):

1>...\main.cpp(42): error C2672: 'Foo::count': no matching overloaded function found
1>...\main.cpp(52): note: see reference to function template instantiation 'unsigned int Foo::totalCount<Dir::U>(void)' being compiled
1>...\main.cpp(42): error C2975: 'unnamed-parameter': invalid template argument for 'Foo::count', expected compile-time constant expression
1>...\main.cpp(27): note: see declaration of 'unnamed-parameter'
1>...\main.cpp(43): error C3536: 'cOther': cannot be used before it is initialized

Единственный способ приблизиться к описанной выше функциональности — это указать как основное направление, так и другое направление в качестве аргументов шаблона следующим образом:

struct Foo {

...

template<Dir d, Dir otherD>
unsigned totalCount() {
auto c = count<d>();
auto cOther = count<otherD>();
return c * cOther;
}

};

int main() {
Foo f(3,2);
std::cout << f.totalCount<Dir::U, Dir::V>() << std::endl;
}

но это не кажется очень элегантным.

0

Решение

otherDir<d>() не является constexprи не может использоваться в аргументе шаблона (count<otherDir<d>()>()).

Вы можете добавить constexpr (а также static) к этому методу,
или используйте старую структуру для обработки этого:

template <Dir> struct otherDir;

template<>
struct otherDir<Dir::U>
{
static constexpr Dir value = Dir::V;
};

template<>
struct otherDir<Dir::V>
{
static constexpr Dir value = Dir::U;
};

демонстрация

0

Другие решения

Возможно, проблема здесь:

auto cOther = count<otherDir<d>()>();

Шаблоны «разрешаются» во время компиляции. Вы должны использовать constexpr за otherDir<d>() потому что просто const не означает, что метод может быть оценен во время компиляции.

Более традиционный подход — иметь структуру otherDir вместо метода. Создайте шаблон структуры, два экземпляра будут с static const value = V или же U,

Или вы можете заменить enum на пустые структуры.

Или, что еще лучше, вы можете попробовать реализовать его без шаблонов и создать класс для измерения и иметь один объект для каждого измерения.

0

По вопросам рекламы [email protected]