如果我有一个简单的结构,如
struct Point { int x, y; };
然后我可以做
int main()
{
Point p1 = { 10 }; // x = 10, y = 0
Point p2 = { 10, 20 }; // x = 10, y = 20
Point p3 = { 10, 20, 30 }; // Compile error: too many initializers for ‘Point’
return 0;
}
我现在希望在Point
初始化时Point
成为一个类但x
和y
变为私有并使用访问器等等时会产生相同的行为。
我的第一次尝试是
class Point
{
public:
Point( std::initializer_list<int> init )
{
switch( init.size() )
{
case 0: x = 0; y = 0; break;
case 1:
{
auto iter = init.begin();
x = *iter++; y = 0;
break;
}
case 2:
{
auto iter = init.begin();
x = *iter++; y = *iter++;
break;
}
default:
throw 0;
break;
}
}
private:
int x, y;
};
哪种有效但将编译时错误更改为运行时错误。现在的问题是:如何使该类的行为与简单结构相同,即当初始化列表太大时导致编译时错误?
环顾四周我找到了
阅读答案和评论我理解了一些constexpr
和static_assert
问题,但我仍然没有找到解决问题的方法。是否有可能在C ++ 11(或C ++ 14)中导致编译时错误?编译器肯定知道它需要的所有内容,对于某人来说似乎可能已经足够了,标准会以某种方式将其推出。
答案 0 :(得分:3)
将初始化列表构造函数替换为以下内容...
Point(int x, int y) :m_x(x), m_y(y) {}
注意,我将私有变量x和y重写为m_x和m_y。
现在,当您尝试初始化具有2个以上参数的Point对象时,您将得到类似于Point是结构时的编译器错误。
答案 1 :(得分:0)
没有编译时间方法来检索std::initializer_list
大小,但您不需要它。
初始化器之类的语法命名为uniform initialization,是c ++ 11的一部分,用于统一,作为自定义名称的语法。
这里有一个适用于Point的完整示例,如您所见,带参数的构造函数可以与初始化列表匹配。
#include <iostream>
class Point {
public:
Point() = default;
Point( int x, int y ) : x_{x}, y_{y} {}
Point( int x ) : x_(x) {}
// or in your case, you can use a default argument
//Point( int x, int y = int{} ) : x_{x}, y_{y} {}
int X() const { return x_; }
int Y() const { return y_; }
private:
int x_{};
int y_{};
};
void DisplayPoint( Point const & p) {
std::cout << "( " << p.X() << ", " << p.Y() << " )" << std::endl;
}
Point GetAPoint() {
return { 3, 5 };
}
int main() {
DisplayPoint( {} );
DisplayPoint( { 1 } );
DisplayPoint( { 1, 2 } );
DisplayPoint( GetAPoint() );
DisplayPoint( Point( 5, 3 ) ); // pre c++11
DisplayPoint( Point{ 5, 3 } ); // in the case the constructor is explicit
}