C++ 如何检查类型';T';拥有';T(标准::初始值设定项列表<;U>;)&x27;建造师
我有一个函数C++ 如何检查类型';T';拥有';T(标准::初始值设定项列表<;U>;)&x27;建造师,c++,templates,constructor,c++17,sfinae,C++,Templates,Constructor,C++17,Sfinae,我有一个函数func(…),它必须分为两个分支 第1分支:类型ThaveT(std::initializer\u list)constructor时的情况 第二分支:类型T没有T(std::initializer\u list)构造函数时的情况 我目前的执行情况如下: 模板 使用has_init_list_ctor=std::enable_if_t>; //具有初始化列表的T的版本 模板< 类型名T, typename=std::启用< std::是否检测到 > > void func(){
func(…)
,它必须分为两个分支
- 第1分支:类型
haveT
constructor时的情况T(std::initializer\u list)
- 第二分支:类型
没有T
构造函数时的情况T(std::initializer\u list)
模板
使用has_init_list_ctor=std::enable_if_t>;
//具有初始化列表的T的版本
模板<
类型名T,
typename=std::启用<
std::是否检测到
>
>
void func(){
//...
}
//不带初始化列表的T的版本
模板<
类型名T,
typename=std::启用<
!std::是否检测到
>
>
void func(){
//...
}
但它有一个缺陷。我不知道如何从T
自动推断类型U
理想的解决方案是:
模板
结构从T推断
{
//实施。
usign type=/*???*/;
};
模板
使用has_init_list_ctor=std::enable_if\t
>>;
但是我不知道如何实现从T中推断
有没有办法解决这个问题?
或者有解决办法吗
更新:
函数func(…)
是对std::alocator\u traits::construct()
的模仿。
我正在尝试实现自己的“分配器”,以便使用std::vector
和智能指针。在正常情况下,我会使用默认的std::alocator_traits
,但这次,我需要从“特殊”池请求内存(这是我实现的,可以称为“虚拟堆”,通过T*get_memory(…)等方法访问)
,该池在mem分配过程中执行其他操作,并提供不同的分配“模式”-很抱歉,它非常通用,但目前是WIP,并且不断变化)
简化了func(…)
(allocator\u traits::construct()
)的实现
模板
类分配器
{
//...
公众:
模板
静止的
std::如果启用,则启用<
std::是否检测到,
无效的
>构造(T*ptr、参数和…参数)
{
新建(ptr)T(std::forward(args);//标准括号//带新位置的构造
}
模板
静止的
std::如果启用,则启用<
!std::是否检测到\u v,
无效的
>构造(T*ptr、参数和…参数)
{
new(ptr)T{std::forward(args)…};//花括号//使用新位置构造
}
//...
};
区别在于能够用花括号构造类型T
(当类型T
没有T(std::initializer\u list)
构造函数时)
有没有办法解决这个问题
是的。不要解决它。你不应该试图猜测用户想要什么样的初始化。只需执行以下操作:
new (ptr) T(std::forward<Args>(args)...)
如果使用括号,我可以传入一个类型为的参数:
struct X_factory { int i; operator X() const { return X{i}; } };
有了保证的拷贝省略,我们无论如何都能得到正确的效果
无论如何,initializer\u list
实际上与问题没有严格的关系。您可能想要的(我不建议这样做)是:
if constexpr(std::is_constructible_v){
新(ptr)T(标准:正向(参数)…);
}否则{
新(ptr)T{std::forward(args)…};
}
或者可能以相反的顺序为direct list initializable编写一个trait。@Barry是对的,这是个坏主意
以下是如何做到这一点:
#include <initializer_list>
#include <utility>
#include <iostream>
struct any_il{
template<class U>
operator std::initializer_list<U>()const{ return {}; }
};
struct foo {
foo(std::initializer_list<int>){}
foo(foo&&)=default;
};
template<class T, class=void>
struct can_from_il:std::false_type{};
template<class T>
struct can_from_il<T, decltype(void( T(any_il{}) ) )>:std::true_type{};
int main(){
std::cout << can_from_il<foo>{}() << can_from_il<int>{}() <<"\n";
}
#包括
#包括
#包括
构造任何{
模板
运算符std::初始值设定项_list()常量{return{};}
};
结构foo{
foo(std::initializer_list){}
foo(foo&&)=默认值;
};
模板
结构can_from_il:std::false_type{};
模板
结构can_from_-il:std::true_类型{};
int main(){
std::cout-XY问题?什么是func()
实际上要做的,为什么你关心T
是否有一个初始化器列表
构造函数来为一些任意的U
(相对于某些特定的U
)这是唯一可能的,如果代码> u>代码>是一个离散类型。如果它是一个必须推导的模板类型,恐怕是不可能的。C++没有这样的工作。如果代码没有什么,<代码> t>代码>可能有多个构造函数,使用不同的<代码> u>代码> <代码> STD::IngalIZErrIListList<代码>。“自动推断类型<代码> u>代码>从<代码> t>代码>可能是无望的。为什么听起来你不是“代码> U>代码?<代码> STD::UngyType Type ?@ JAROD42号<代码> U>代码>可能与<代码> ARGS…< /代码>无关。请考虑<代码>向量{ 1, 2, 3 } <代码> >或代码>向量{a”、“BC”、“DEF”}。
你能详细说明工厂应该如何使用吗?
if constexpr (std::is_constructible_v<T, Args...>) {
new (ptr) T(std::forward<Args>(args)...);
} else {
new (ptr) T{std::forward<Args>(args)...};
}
#include <initializer_list>
#include <utility>
#include <iostream>
struct any_il{
template<class U>
operator std::initializer_list<U>()const{ return {}; }
};
struct foo {
foo(std::initializer_list<int>){}
foo(foo&&)=default;
};
template<class T, class=void>
struct can_from_il:std::false_type{};
template<class T>
struct can_from_il<T, decltype(void( T(any_il{}) ) )>:std::true_type{};
int main(){
std::cout << can_from_il<foo>{}() << can_from_il<int>{}() <<"\n";
}