Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何检查类型';T';拥有';T(标准::初始值设定项列表<;U>;)&x27;建造师_C++_Templates_Constructor_C++17_Sfinae - Fatal编程技术网

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分支:类型
    T
    have
    T(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(){
//... 
}
//不带初始化列表的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";
}