初始化列表和转换为一切,构造顺序
initializer list and conversion to everything, construction order
情况如:
#include <utility>
#include <typeinfo>
#include <iostream>
struct C1
{
char const* str;
template <typename T> operator T() const { std::cout << "Convert to " << typeid(T).name() << "\n"; return {}; }
};
struct C2
{
C2(C1 const&) { std::cout << "C2(C1)\n"; }
C2(std::initializer_list<std::pair<char const*, int>>) { std::cout << "C2(list)\n"; }
};
int main()
{
C1 c1{};
C2 c2{c1};
}
输出表明正在调用 C2(list)
。
我想为 C1
参数调用 C2(C1)
,但我需要 std::initializer 列表的参数保持可推导和可转换,我不能用可变参数替换它- 模板版本。我只是想控制构建顺序,但是这里//2甚至不是模板。假设 type std::pair 可以在正常情况下反序列化。可以使用 C++14
您可以使用 explicit 关键字来防止构造函数进行隐式类型转换:
explicit C2(std::initializer_list<std::pair<char const*, int>>) {} // 2
参见:What does the explicit keyword mean in C++?
以下 selects C2(C1)
两种样式的样式,{...}
和 ({...})
(在严格的 C++11 标准中,对于 ({...})
样式,它将 select 第二个,因为 C1
是一个聚合和适用于它的特殊规则。对于更新的标准,情况不再如此。)。这通过使第二个构造函数不再是初始化构造函数来实现。
template<typename T>
struct id { typedef T type; };
struct C1 {
char const* str;
template <typename T> operator T() const
{ std::cout << "Convert to " << typeid(T).name() << "\n"; return {}; }
};
struct C2 {
C2(C1);
template<typename T = std::initializer_list<std::pair<char const*, int>>>
C2(typename id<T>::type);
};
int main() {
C1 c1{};
C2 c2{c1};
C2 c21({c1});
}
情况如:
#include <utility>
#include <typeinfo>
#include <iostream>
struct C1
{
char const* str;
template <typename T> operator T() const { std::cout << "Convert to " << typeid(T).name() << "\n"; return {}; }
};
struct C2
{
C2(C1 const&) { std::cout << "C2(C1)\n"; }
C2(std::initializer_list<std::pair<char const*, int>>) { std::cout << "C2(list)\n"; }
};
int main()
{
C1 c1{};
C2 c2{c1};
}
输出表明正在调用 C2(list)
。
我想为 C1
参数调用 C2(C1)
,但我需要 std::initializer 列表的参数保持可推导和可转换,我不能用可变参数替换它- 模板版本。我只是想控制构建顺序,但是这里//2甚至不是模板。假设 type std::pair 可以在正常情况下反序列化。可以使用 C++14
您可以使用 explicit 关键字来防止构造函数进行隐式类型转换:
explicit C2(std::initializer_list<std::pair<char const*, int>>) {} // 2
参见:What does the explicit keyword mean in C++?
以下 selects C2(C1)
两种样式的样式,{...}
和 ({...})
(在严格的 C++11 标准中,对于 ({...})
样式,它将 select 第二个,因为 C1
是一个聚合和适用于它的特殊规则。对于更新的标准,情况不再如此。)。这通过使第二个构造函数不再是初始化构造函数来实现。
template<typename T>
struct id { typedef T type; };
struct C1 {
char const* str;
template <typename T> operator T() const
{ std::cout << "Convert to " << typeid(T).name() << "\n"; return {}; }
};
struct C2 {
C2(C1);
template<typename T = std::initializer_list<std::pair<char const*, int>>>
C2(typename id<T>::type);
};
int main() {
C1 c1{};
C2 c2{c1};
C2 c21({c1});
}