从模板专业化获得对 class 成员的访问权限
Gaining access to class members from template specialization
所以,我基本上想"add" class 额外的东西,这取决于它使用的是什么模板参数,然后为它取别名以获得更好的界面。像这样:
template<typename T, std::size_t N>
struct basic_foo
{
T data[N];
};
//what you see as comments is what i tried
template<> //template<typename T, std::size_t N>
struct basic_foo<double, 3> //: public basic_foo<T, N>
{
void foo_fun()
{
std::cout << "I'm a foo function!";
for (auto i : data) std::cout << i << " ";
}
};
template<> //template<typename T, std::size_t N>
struct basic_foo<int, 2> //: public basic_foo<T, N>
{
void bar_fun()
{
std::cout << "I'm a bar function!";
for (auto i : data) std::cout << i << " ";
}
};
using foo = basic_foo<double, 3>;
using bar = basic_foo<int, 2>;
int main()
{
foo a = { 12.0, 2.4, 3.0 };
bar b = { 1, 2 };
}
问题是我无法在专业化中访问 data
。
有办法吗?还是我应该重新考虑我的结构性决定?
您的代码现在无法编译,因为您的专业化中没有 data
成员。你试过从主模板继承,差点搞定
制作一个basic_foo_base
class(或struct
)模板,在其中存储data
和不需要特化的函数:
template <typename T, std::size_t N>
struct basic_foo_base
{
T data[N];
};
那只是将 _base
添加到现有定义的名称中。现在,再次定义 basic_foo
:
template <typename T, std::size_t N>
struct basic_foo : basic_foo_base<T, N>
{
};
这就是专业化的样子:
template <>
// instantiate the base with the same template arguments
struct basic_foo<double, 3> : public basic_foo_base<double, 3>
{
};
我希望我做对了一切。
编辑:不,我没有。
由于继承,basic_foo
将不再是聚合。我们需要添加一些代码,所以初始化:
foo a = { 12.0, 2.4, 3.0 };
再次有效。也就是说,定义一个采用 std::initializer_list
:
的隐式构造函数
basic_foo_base(std::initializer_list<T> const& il)
{
std::copy(il.begin(), il.end(), std::begin(data));
}
并添加
using basic_foo_base::basic_foo_base;
// or, for the primary template:
using basic_foo_base<T, N>::basic_foo_base;
在所有 basic_foo
中将该构造函数包含到重载决议中。
替代包含 data
的公共基础 class,您可以完全专精:
template<>
struct basic_foo<double, 3>
{
double data[3]; // Should be here.
void foo_fun()
{
std::cout << "I'm a foo function!";
for (auto i : data) std::cout << i << " ";
}
};
所以,我基本上想"add" class 额外的东西,这取决于它使用的是什么模板参数,然后为它取别名以获得更好的界面。像这样:
template<typename T, std::size_t N>
struct basic_foo
{
T data[N];
};
//what you see as comments is what i tried
template<> //template<typename T, std::size_t N>
struct basic_foo<double, 3> //: public basic_foo<T, N>
{
void foo_fun()
{
std::cout << "I'm a foo function!";
for (auto i : data) std::cout << i << " ";
}
};
template<> //template<typename T, std::size_t N>
struct basic_foo<int, 2> //: public basic_foo<T, N>
{
void bar_fun()
{
std::cout << "I'm a bar function!";
for (auto i : data) std::cout << i << " ";
}
};
using foo = basic_foo<double, 3>;
using bar = basic_foo<int, 2>;
int main()
{
foo a = { 12.0, 2.4, 3.0 };
bar b = { 1, 2 };
}
问题是我无法在专业化中访问 data
。
有办法吗?还是我应该重新考虑我的结构性决定?
您的代码现在无法编译,因为您的专业化中没有 data
成员。你试过从主模板继承,差点搞定
制作一个basic_foo_base
class(或struct
)模板,在其中存储data
和不需要特化的函数:
template <typename T, std::size_t N>
struct basic_foo_base
{
T data[N];
};
那只是将 _base
添加到现有定义的名称中。现在,再次定义 basic_foo
:
template <typename T, std::size_t N>
struct basic_foo : basic_foo_base<T, N>
{
};
这就是专业化的样子:
template <>
// instantiate the base with the same template arguments
struct basic_foo<double, 3> : public basic_foo_base<double, 3>
{
};
我希望我做对了一切。
编辑:不,我没有。
由于继承,basic_foo
将不再是聚合。我们需要添加一些代码,所以初始化:
foo a = { 12.0, 2.4, 3.0 };
再次有效。也就是说,定义一个采用 std::initializer_list
:
basic_foo_base(std::initializer_list<T> const& il)
{
std::copy(il.begin(), il.end(), std::begin(data));
}
并添加
using basic_foo_base::basic_foo_base;
// or, for the primary template:
using basic_foo_base<T, N>::basic_foo_base;
在所有 basic_foo
中将该构造函数包含到重载决议中。
替代包含 data
的公共基础 class,您可以完全专精:
template<>
struct basic_foo<double, 3>
{
double data[3]; // Should be here.
void foo_fun()
{
std::cout << "I'm a foo function!";
for (auto i : data) std::cout << i << " ";
}
};