嵌套模板 C++
Nested template C++
我有一个模板 class 的形式:
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::Type Type;
...
private:
void sample(int iteration) {...}
}
我想为 ContainerType 是 Vector 的情况创建特定版本的函数示例。其中Vector本身就是一个模板class,但是我不知道这个Vector持有的是哪种类型的值
我的直觉是在头文件中创建这个:
template<typename Type>
ConfIntParamStat<Vector<Type> >::sample(int iteration) {
...
}
但是编译不通过,clang的报错是:
error: nested name specifier 'ConfIntParamStat<Vector<Type> >::' for declaration does not refer into a class, class template or class template partial specialization
是否可以使用其他语法?
您可以利用重载机制和标签分发:
#include <vector>
template <class T>
struct Tag { };
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::value_type Type;
//...
// private:
void sample(int iteration) {
sample_impl(Tag<ContainerType>(), iteration);
}
template <class T>
void sample_impl(Tag<std::vector<T> >, int iteration) {
//if vector
}
template <class T>
void sample_impl(Tag<T>, int iteration) {
//if not a vector
}
};
int main() {
ConfIntParamStat<std::vector<int> > cips;
cips.sample(1);
}
正如 skypjack 提到的,这种方法在使用 const 时有一点吸引力。如果您没有使用 c++11
(我怀疑您没有使用,因为您对嵌套模板使用了 > >
语法),您可以按如下方式解决此问题:
#include <iostream>
#include <vector>
template <class T>
struct Tag { };
template <class T>
struct Decay {
typedef T Type;
};
template <class T>
struct Decay<const T> {
typedef T Type;
};
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::value_type Type;
//...
// private:
void sample(int iteration) {
sample_impl(Tag<typename Decay<ContainerType>::Type>(), iteration);
}
template <class T>
void sample_impl(Tag<std::vector<T> >, int iteration) {
std::cout << "vector specialization" << std::endl;
}
template <class T>
void sample_impl(Tag<T>, int iteration) {
std::cout << "general" << std::endl;
}
};
int main() {
ConfIntParamStat<const std::vector<int> > cips;
cips.sample(1);
}
如果您不想专门化模板并且正在寻找仅限成员的专门化,请尝试以下
#include <iostream>
#include <vector>
using namespace std;
template <typename ContainerType>
class Something {
public:
void do_something(int);
template <typename Which>
struct do_something_implementation {
void operator()() {
cout << "general implementation" << endl;
}
};
template <typename Which>
struct do_something_implementation<vector<Which>> {
void operator()() {
cout << "specialized implementation for vectors" << endl;
}
};
};
template <typename ContainerType>
void Something<ContainerType>::do_something(int) {
do_something_implementation<ContainerType>{}();
}
int main() {
Something<double> something;
something.do_something(1);
return 0;
}
如果你的目的是专门化一个函数,我会像这样重载函数
#include <iostream>
#include <vector>
using namespace std;
template <typename ContainerType>
class Something {
public:
void do_something(int);
template <typename Type>
void do_something(const vector<Type>&);
};
template <typename ContainerType>
void Something<ContainerType>::do_something(int) {
cout << "Called the general method for do_something" << endl;
}
template <typename ContainerType>
template <typename Type>
void Something<ContainerType>::do_something(const vector<Type>&) {
cout << "Called the specialised method" << endl;
}
int main() {
vector<int> vec{1, 2, 3};
Something<double> something;
something.do_something(1);
something.do_something(vec);
return 0;
}
这就是为什么 full/explicit 不需要函数模板特化的主要原因。重载允许几乎相同的效果!
注意这是一篇与您的问题相关的好文章! http://www.gotw.ca/publications/mill17.htm
另一种方法是合成。
添加 sample
的行为可以被认为是 class 实现的一个组成部分。如果我们删除将样本添加到此模板的实现 class,我们就可以仅部分特化此离散组件。
例如:
#include <vector>
//
// default implementation of the sample component
//
template<class Outer>
struct implements_sample
{
using sample_implementation = implements_sample;
// implements one function
void sample(int iteration) {
// default actions
auto self = static_cast<Outer*>(this);
// do something with self
// e.g. self->_samples.insert(self->_samples.end(), iteration);
}
};
// refactor the container to be composed of component(s)
template<typename ContainerType>
class ConfIntParamStat
: private implements_sample<ConfIntParamStat<ContainerType>>
{
using this_class = ConfIntParamStat<ContainerType>;
public:
// I have added a public interface
void activate_sample(int i) { sample(i); }
// here we give the components rights over this class
private:
friend implements_sample<this_class>;
using this_class::sample_implementation::sample;
ContainerType _samples;
};
//
// now specialise the sample function component for std::vector
//
template<class T, class A>
struct implements_sample<ConfIntParamStat<std::vector<T, A>>>
{
using sample_implementation = implements_sample;
void sample(int iteration) {
auto self = static_cast<ConfIntParamStat<std::vector<T, A>>*>(this);
// do something with self
self->_samples.push_back(iteration);
}
};
int main()
{
ConfIntParamStat< std::vector<int> > cip;
cip.activate_sample(1);
cip.activate_sample(2);
}
我有一个模板 class 的形式:
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::Type Type;
...
private:
void sample(int iteration) {...}
}
我想为 ContainerType 是 Vector 的情况创建特定版本的函数示例。其中Vector本身就是一个模板class,但是我不知道这个Vector持有的是哪种类型的值
我的直觉是在头文件中创建这个:
template<typename Type>
ConfIntParamStat<Vector<Type> >::sample(int iteration) {
...
}
但是编译不通过,clang的报错是:
error: nested name specifier 'ConfIntParamStat<Vector<Type> >::' for declaration does not refer into a class, class template or class template partial specialization
是否可以使用其他语法?
您可以利用重载机制和标签分发:
#include <vector>
template <class T>
struct Tag { };
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::value_type Type;
//...
// private:
void sample(int iteration) {
sample_impl(Tag<ContainerType>(), iteration);
}
template <class T>
void sample_impl(Tag<std::vector<T> >, int iteration) {
//if vector
}
template <class T>
void sample_impl(Tag<T>, int iteration) {
//if not a vector
}
};
int main() {
ConfIntParamStat<std::vector<int> > cips;
cips.sample(1);
}
正如 skypjack 提到的,这种方法在使用 const 时有一点吸引力。如果您没有使用 c++11
(我怀疑您没有使用,因为您对嵌套模板使用了 > >
语法),您可以按如下方式解决此问题:
#include <iostream>
#include <vector>
template <class T>
struct Tag { };
template <class T>
struct Decay {
typedef T Type;
};
template <class T>
struct Decay<const T> {
typedef T Type;
};
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::value_type Type;
//...
// private:
void sample(int iteration) {
sample_impl(Tag<typename Decay<ContainerType>::Type>(), iteration);
}
template <class T>
void sample_impl(Tag<std::vector<T> >, int iteration) {
std::cout << "vector specialization" << std::endl;
}
template <class T>
void sample_impl(Tag<T>, int iteration) {
std::cout << "general" << std::endl;
}
};
int main() {
ConfIntParamStat<const std::vector<int> > cips;
cips.sample(1);
}
如果您不想专门化模板并且正在寻找仅限成员的专门化,请尝试以下
#include <iostream>
#include <vector>
using namespace std;
template <typename ContainerType>
class Something {
public:
void do_something(int);
template <typename Which>
struct do_something_implementation {
void operator()() {
cout << "general implementation" << endl;
}
};
template <typename Which>
struct do_something_implementation<vector<Which>> {
void operator()() {
cout << "specialized implementation for vectors" << endl;
}
};
};
template <typename ContainerType>
void Something<ContainerType>::do_something(int) {
do_something_implementation<ContainerType>{}();
}
int main() {
Something<double> something;
something.do_something(1);
return 0;
}
如果你的目的是专门化一个函数,我会像这样重载函数
#include <iostream>
#include <vector>
using namespace std;
template <typename ContainerType>
class Something {
public:
void do_something(int);
template <typename Type>
void do_something(const vector<Type>&);
};
template <typename ContainerType>
void Something<ContainerType>::do_something(int) {
cout << "Called the general method for do_something" << endl;
}
template <typename ContainerType>
template <typename Type>
void Something<ContainerType>::do_something(const vector<Type>&) {
cout << "Called the specialised method" << endl;
}
int main() {
vector<int> vec{1, 2, 3};
Something<double> something;
something.do_something(1);
something.do_something(vec);
return 0;
}
这就是为什么 full/explicit 不需要函数模板特化的主要原因。重载允许几乎相同的效果!
注意这是一篇与您的问题相关的好文章! http://www.gotw.ca/publications/mill17.htm
另一种方法是合成。
添加 sample
的行为可以被认为是 class 实现的一个组成部分。如果我们删除将样本添加到此模板的实现 class,我们就可以仅部分特化此离散组件。
例如:
#include <vector>
//
// default implementation of the sample component
//
template<class Outer>
struct implements_sample
{
using sample_implementation = implements_sample;
// implements one function
void sample(int iteration) {
// default actions
auto self = static_cast<Outer*>(this);
// do something with self
// e.g. self->_samples.insert(self->_samples.end(), iteration);
}
};
// refactor the container to be composed of component(s)
template<typename ContainerType>
class ConfIntParamStat
: private implements_sample<ConfIntParamStat<ContainerType>>
{
using this_class = ConfIntParamStat<ContainerType>;
public:
// I have added a public interface
void activate_sample(int i) { sample(i); }
// here we give the components rights over this class
private:
friend implements_sample<this_class>;
using this_class::sample_implementation::sample;
ContainerType _samples;
};
//
// now specialise the sample function component for std::vector
//
template<class T, class A>
struct implements_sample<ConfIntParamStat<std::vector<T, A>>>
{
using sample_implementation = implements_sample;
void sample(int iteration) {
auto self = static_cast<ConfIntParamStat<std::vector<T, A>>*>(this);
// do something with self
self->_samples.push_back(iteration);
}
};
int main()
{
ConfIntParamStat< std::vector<int> > cip;
cip.activate_sample(1);
cip.activate_sample(2);
}