在cppreference/variant(4)上,转换构造函数描述如下:
转换构造函数。构造一个变体持有替代类型
T_j
,如果在范围内同时存在来自范围内F(std::forward<T>(t))
的每个F(T_i)
的虚函数T_i
的重载,则将通过重载决策选择表达式Types...
,除了:
- 如果声明
F(T_i)
对某些发明变量T_i x[] = { std::forward<T>(t) };
有效,则仅考虑重载x
;- 如果
T_i
(可能是cv合格的)bool
,F(T_i)
只考虑std:remove_cvref_t<T>
也是bool
。
由于我与Visual Studio 2010绑定,但仍希望有一个std-variant,我自己实现了一个。我遇到的问题以及我要求解决的问题是如何在VS10中实现第一个要点?如果表达式如何丢弃虚函数F(T_i)
的重载
T_i x[] = { std::forward<T>(t) };
是不是形成了?
在VS15中我能写:
template<class T> using array_t = T[];
template<class UserType, class T_i, class = void>
struct Single_FUN_T_i {
using type = void(*)();
};
template<class UserType, class T_i>
struct Single_FUN_T_i<UserType, T_i,
decltype( array_t<T_i>{ std::declval<UserType>() }, void() )> {
// ^^ Here I check whether T_i[]{ declval<T>() } compiles
using type = T_i(*)(T_i);
};
但是在VS10中,这不起作用,因为表达式array_t<T_i>{ std::declval<UserType>() }
似乎不受支持(我知道别名模板也不会工作,但这不是问题)。
我想这可能会让你更进一步。而不是使用数组初始化,使用declval实例化一个数组并尝试在其中插入元素。
// TestSfinae.cpp:该文件包含'main'函数。程序执行开始和结束。 //
#include <iostream>
#include <utility>
#include <iostream>
#include <string>
#include <boost/utility/declval.hpp>
template<class A, class B, class = void>
struct X {
std::string msg;
X():msg("Fail"){};
};
template<class A, class B>
struct X<A, B, decltype(boost::declval<A[]>()[0]=boost::declval<B>(), void()) >
{
std::string msg;
X():msg("Pass"){};
};
int main(){
X<int,int> x;
std::cerr << x.msg << std::endl;;
X<int,std::string> y;
std::cerr << y.msg << std::endl;;
}
预期的结果是
Pass
Fail
不幸的是,我认为,我无法用VS10解决这个问题。这是因为the aggregate initilization T object[]{args...}
仅在C ++ 11之后可用,而不是VS10的一部分。要在聚合启动时做SFINAE我不能写decltype(T x[]= {arg})
但是必须像我的例子那样写decltype(array_t<T>{arg})
。