提问人:user1470475 提问时间:6/14/2023 最后编辑:user1470475 更新时间:6/14/2023 访问量:52
根据类模板参数对类成员使用不同的构造函数
Use different constructor for class member based on class template parameter
问:
存在这样一种情况:模板化类包含模板化成员,并且必须使用正确的构造函数(取决于类模板)构造该成员对象。简化示例:
#include <stdexcept>
#include <memory>
#include <iostream>
#include <vector>
template<int N=0>
struct A
{
const int n_;
A(int n, double)
: n_{n}
{
static_assert(N <= 0);
}
A(double)
: n_{N}
{
static_assert(N > 0);
}
};
template<int N=0>
struct B
{
const std::vector<int> m_;
// Solution with unique_ptr class member to an A<N> object
std::unique_ptr<A<N>> a_uptr_;
B(const std::vector<int>& m, double x)
: m_{m},
a_uptr_{N > 0 ? std::make_unique<A<N>>(x) : std::make_unique<A<N>>(m.size(), x)}
{}
// Solution with class member A<N> object
// A<N> a_;
// B(const std::vector<int>& m, double x)
// : m_{m},
// a_{ <????????????????????> }
// {}
};
int main()
{
std::vector<int> m{1,2,3};
B b1(m, 0);
B<2> b2(m, 0);
std::cout << b1.a_uptr_->n_ << ", " << b2.a_uptr_->n_ << std::endl;
}
Q1:有没有办法只有一个类成员(而不是唯一的 ptr)并让它调用正确的构造函数?使用也许???A<N>
std::integer_sequence
(Q2:我是不是想多了,即我真的应该担心必须将 obj 放在堆上的性能吗?A<N>
答:
1赞
463035818_is_not_an_ai
6/14/2023
#1
假设问题只是关于,这应该不会改变......
那么你面临的就是我所说的“初始值设定项列表中成员的复杂构造”,而解决方案通常是一个静态方法:B
A
#include <stdexcept>
#include <iostream>
#include <vector>
template<int N=0>
struct A {
const int n_;
A(int n, double) : n_{n} {
if constexpr (N > 0) throw std::runtime_error("wrong constructor for N > 0");
}
A(double) : n_{N} {
if constexpr (N <= 0) throw std::runtime_error("wrong constructor for N <= 0");
}
};
template<int N=0>
struct B {
const std::vector<int> m_;
A<N> a_uptr_;
B(const std::vector<int>& m, double x)
: m_{m},
a_uptr_{make_AN(m,x)}
{}
private:
static A<N> make_AN(const std::vector<int>& m,double x) {
if constexpr (N>0) return x;
else return {m.size(),x};
}
};
int main() {
std::vector<int> m{1,2,3};
B b1(m, 0);
B<2> b2(m, 0);
std::cout << b1.a_uptr_.n_ << ", " << b2.a_uptr_.n_ << std::endl;
}
或者正如评论中提到的(一些程序员家伙和 n.m.),简单地.也许你害怕无论如何都被省略的副本。a_{N > 0 ? A<N>{m} : A<N>{m, x}}
但是,您应该考虑重写,以便使用 和 调用 时出现编译时错误。A
A<N>::A(int,double)
N > 0
A<N>::A(double)
N <= 0
评论
0赞
Oersted
6/14/2023
@463035818_is_not_a_number,我对 .您能否详细说明使编译器使用适当构造函数的机制。特别是,第二个看起来像是从 到 的隐式转换,它没有定义,因此我一定是错的。return
make_AN
std::initializer_list
A<N>
1赞
463035818_is_not_an_ai
6/15/2023
@Oersted en.cppreference.com/w/cpp/language/list_initialization 案例 (8)
0赞
Oersted
6/15/2023
@463035818_is_not_a_number,为了正确,情况 (8) 说 ̀return {m.size(),x} ̀ 实际上与 ̀̀̀{m.size(),x}' 不是(允许混合类型)相同。我说得对吗?A<N>{m.size(),x}
std::initializer_list
评论
a_
A<N>(x)
A<N>(,.size(), x)
A
throw
static_assert
A