2015-10-15 53 views
0

情状:初始化列表和转换的一切,为了建设

#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)被调用。

我想C2(C1)被调用为C1参数,但我需要std :: initializer列表的参数保持可以被推导和转换,并且我不能用variadic-templated版本替换它。我只想控制施工顺序,但这里// 2甚至不是模板。假设类型std :: pair可以在正常情况下被反序列化。 C++ 14可用于

+1

的问题是'{}''调用构造函数initializer_list',其中有超过一般的构造函数优先。把它叫做C2 C2(C1)'有什么不对?或者你想在你的API中使用这种特定的语法? – romeric

+1

我想你应该用C1可以转换的实际类型替换'operator T'。或者甚至更好,使用一个命名函数而不是转换运算符,并在需要时实际调用该函数。 –

+0

@romeric这不仅仅是我的界面。如果我在内部使用它,我会这样做 –

回答

0

下选择C2(C1)风格时尚风格,{...}({...})(在严格的C++ 11标准中,对于({...})样式,它将选择第二个,因为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}); 
} 
+0

这很好。只用于初始化列表,我需要加两个大括号,比如'C2 c22 {{{“bbb”,3},{“aaa”,3}}};'而不仅仅是'C2 c22 {{“bbb”,3 },{“aaa”,3}};' –

0

您可以使用明确关键字,以防止从构造隐式类型转换:

explicit C2(std::initializer_list<std::pair<char const*, int>>) {} // 2 

参见:What does the explicit keyword mean in C++?

+0

是的。我可以,但我需要std :: pair与可转换参数保持可转换,如果我使用明确的关键字,我将失去转换 –

+0

您将需要添加更多的构造函数执行允许的转换(例如,采取std: :配对作为参数)。 –

+0

这将是十几个构造函数:) –