问题
I have been looking at how the initializer_list
is implemented so I found section 18.9 of the standard and found a simple enough looking interface. I thought it would be instructive to make my own version which I named MyNamespace::InitializerList
and a use case:
template<class T>
class ArrayPrinter
{
public:
ArrayPrinter(MyNamespace::InitializerList<T> list)
{
for (auto i : list) cout << i << endl;
}
};
...
ArrayPrinter ap{ {1,2,3} };
I was surprised to find that this did not work and the compiler complained that it couldn't find a suitable constructor (it wanted to give me 3 arguments but section 18.9 only describes a default constructor).
After a bit of fiddling I found that my class had to be named exactly std::initializer_list
in order to work. I could also alias std::initializer_list
it into MyNamespace
but I could not alias MyNamespace::InitializerList
asstd::initializer_list
.
It seems that this it is not really a language feature as it depends on the standard library?
The main point to my question is why the name is so important and what were those 3 arguments it was trying to pass to the constructor?
回答1:
The name is important because the standard says it is. The standard needs some way for you to be able to say, "this constructor can be passed a braced-init-list containing a sequence values of the type T". That way was given the name "std::initializer_list
".
You cannot make a class that has all of the language properties of initializer_list
. You can make one that satisfies the conditions of the type specified by section 18.9 of the standard. But you'll notice that the only constructor specified there is a default constructor. The only way to create an initializer_list
with actual elements relies on the compiler, not user-land code.
So you can't replicate everything about initializer_list
. Just as you can't replicate std::type_info
. The C++ standard library is not optional.
来源:https://stackoverflow.com/questions/18164353/implementation-of-stdinitializer-list