C++ 对于多个参数,_是可转换的吗
假设出于任何原因,我没有std::is_convertible,并且希望自己实现它。该标准的表述大致如下: 当且仅当以下代码中的返回表达式格式良好(包括对函数返回类型的任何隐式转换)时,应满足模板专用化的谓词条件C++ 对于多个参数,_是可转换的吗,c++,c++11,implicit-conversion,sfinae,typetraits,C++,C++11,Implicit Conversion,Sfinae,Typetraits,假设出于任何原因,我没有std::is_convertible,并且希望自己实现它。该标准的表述大致如下: 当且仅当以下代码中的返回表达式格式良好(包括对函数返回类型的任何隐式转换)时,应满足模板专用化的谓词条件是可转换的: To f() { return declval<From>(); } To f() { return {declval<From>()...}; } 这似乎是有意为之,就我所知,它也做了同样的事情 现在我可以区分隐式和显式(或根本
是可转换的
:
To f() {
return declval<From>();
}
To f() {
return {declval<From>()...};
}
这似乎是有意为之,就我所知,它也做了同样的事情
现在我可以区分隐式和显式(或根本没有)构造函数:
struct A {};
struct B {};
struct Test {
Test(A);
explicit Test(B);
};
int main() {
std::cout << my_is_convertible<Test, A>::value; // true
std::cout << my_is_convertible<Test, B>::value; // false
return 0;
}
为了实现它,我采取了显而易见的方式:
template <typename To_, typename... From_>
class my_is_convertible_many {
private:
template <typename To>
struct indirector {
indirector(To);
};
template <typename To, typename... From>
struct tag {};
template <typename To, typename... From>
static auto test(tag<To, From...>)
-> decltype(indirector<To>({std::declval<From>()...}), std::true_type());
static auto test(...)
-> std::false_type;
public:
static constexpr bool value = decltype(test(tag<To_, From_...>()))::value;
};
错误是关于试图隐式调用显式构造函数,在gcc上听起来像这样:
main.cpp: In substitution of 'template<class To, class ... From> static decltype (((my_is_convertible_many<To_, From_>::indirector<To>)({(declval<From>)()...}), std::true_type())) my_is_convertible_many<To_, From_>::test(my_is_convertible_many<To_, From_>::tag<To, From ...>) [with To = To; From = {From ...}; To_ = Test; From_ = {C, C}] [with To = Test; From = {C, C}]':
main.cpp:21:73: required from 'constexpr const bool my_is_convertible_many<Test, C, C>::value'
main.cpp:37:54: required from here
main.cpp:17:97: error: converting to 'Test' from initializer list would use explicit constructor 'Test::Test(C, C)'
static auto test(tag<To, From...>) -> decltype(indirector<To>({std::declval<From>()...}), std::true_type());
^
main.cpp:替换“模板静态decltype(((my_is_convertible_many::indirector)({(declval)(…]),std::true_type())my_is_convertible_many::test(my_is_convertible_many::tag)[with To=To;From={From…};To=test From={C,C}][with To=test From={C,C}]:
main.cpp:21:73:constexpr const bool my_是可转换的\u many::value'中必需的
main.cpp:37:54:此处需要
main.cpp:17:97:错误:从初始值设定项列表转换为“Test”将使用显式构造函数“Test::Test(C,C)”
静态自动测试(tag)->decltype(indirector({std::declval()…}),std::true_type());
^
这是明智的。一、 但是,希望这个test
重载被忽略,而另一个重载将被使用,因此不会产生错误
所以问题是:为什么不会发生这种情况,我能做些什么呢?gcc最近刚刚发布,4.9版将接受该代码。clang也接受它,所以代码可能很好。这并不能告诉您如何使用旧版本的GCC来解决这个问题,对不起。对我来说,这看起来不像<代码> ISTHORITY 。但是<代码> iSuthTeaTyrByx使用< /Calp> > GCC源代码说:“当从init列表转换时,我们考虑显式构造函数,但实际上试图调用一个构造函数是一个错误。”听起来可能是故意的?还是忘了斯芬纳?在任何情况下,修改它的补丁都是微不足道的(cp/call.c中有1或2行)。如果你没有得到一个令人信服的答案,即代码是非法的,请向gcc提交PR。顺便问一下,你有没有检查过其他编译器?@MikeKinghan谢谢,这是一个bug。在gcc-4.9()中修复。下次请别忘了提交一个bug。@Marglisse:也许你应该把它作为一个答案,这样这个问题就可以从未回答的问题列表中删除了?
struct A {};
struct B {};
struct C {};
struct Test {
Test(A, A);
//Test(B, B);
explicit Test(C, C);
};
int main() {
std::cout << my_is_convertible_many<Test, A, A>::value; // true, correct
std::cout << my_is_convertible_many<Test, B, B>::value; // false, correct
std::cout << my_is_convertible_many<Test, C, C>::value; // error
return 0;
}
main.cpp: In substitution of 'template<class To, class ... From> static decltype (((my_is_convertible_many<To_, From_>::indirector<To>)({(declval<From>)()...}), std::true_type())) my_is_convertible_many<To_, From_>::test(my_is_convertible_many<To_, From_>::tag<To, From ...>) [with To = To; From = {From ...}; To_ = Test; From_ = {C, C}] [with To = Test; From = {C, C}]':
main.cpp:21:73: required from 'constexpr const bool my_is_convertible_many<Test, C, C>::value'
main.cpp:37:54: required from here
main.cpp:17:97: error: converting to 'Test' from initializer list would use explicit constructor 'Test::Test(C, C)'
static auto test(tag<To, From...>) -> decltype(indirector<To>({std::declval<From>()...}), std::true_type());
^