在cppreference/variant(4)上,转换构造函数的描述如下:
转换构造函数。构造一个包含替代类型
T_j
的变体,如果F(std::forward<T>(t))
中每个F(T_i)
的虚函数T_i
都有重载,则可以通过重载解析为表达式Types...
选择该变体。 1}}同时作用域,除了:
- 仅当声明
F(T_i)
对某些发明变量T_i x[] = { std::forward<T>(t) };
有效时,才考虑重载x
;- 如果
T_i
是(可能是简历合格的)bool
,则只有F(T_i)
也是std:remove_cvref_t<T>
时,才考虑使用bool
。
由于我与Visual Studio 2010紧密联系,但仍然希望拥有一个std变量,因此我自己实现了一个。我要解决的问题是,如何在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>() }
(我知道别名模板也不会起作用,但这不是问题)。
答案 0 :(得分:0)
我认为这可以使您更进一步。不要使用数组初始化,而要使用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
答案 1 :(得分:0)
不幸的是,我认为我无法使用VS10解决此问题。这是因为the aggregate initilization T object[]{args...}
仅从C ++ 11开始可用,但尚未成为VS10的一部分。为了对聚合初始化进行SFINAE,我不能写decltype(T x[]= {arg})
,但必须像我的示例那样写decltype(array_t<T>{arg})
。