gpt4 book ai didi

c++ - 在构造函数中限制可变参数模板的可接受方式

转载 作者:太空狗 更新时间:2023-10-29 20:59:11 27 4
gpt4 key购买 nike

为了解释我的问题,我将首先粘贴一些示例代码然后提出相关问题。

template< typename... CONDITIONS >
struct all_true;

template<>
struct all_true<>
{
const static bool value = true;
};

template< typename CONDITION, typename... CONDITIONS >
struct all_true< CONDITION, CONDITIONS... >
{
const static bool value = CONDITION::value && all_true<CONDITIONS...>::value;
};

template< class T >
class myobject
{
struct placeholder {};

template< typename... Ts >
struct CheckVaradicArgs
{
typedef
typename std::enable_if<
all_true< std::is_convertible<Ts, T>... >::value
, placeholder >::type type;
};

template< typename... Ts >
myobject( placeholder check, Ts... params )
{}
public:

myobject( const myobject& other )
{
std::cout << "Copy constructor" << std::endl;
}

template< typename... Ts >
myobject( Ts... params )
: myobject( typename CheckVaradicArgs<Ts...>::type(), params... )
{
std::cout << "Ts constructor with " << sizeof...(params) << std::endl;
}

};

在上面的代码中,我有一个模板化类型 myobject。希望它有一个构造函数,该构造函数接受任意数量的类型,这些类型可转换为模板化 myobject 的类型。

此外,我希望拥有通常的复制构造函数以及其他可能采用可与 myobject 一起使用的特殊类型的构造函数。

我遇到的问题是如何编写使用可变参数模板的构造函数。显然它不应该接受我有其他构造函数的任何类型。然而,它应该接受通过特定测试的类型(在这个例子中,是 is_convertible 测试)。

我解决这个问题的方法是上面的解决方案,它适用于 GCC - 可变参数构造函数将参数传递给辅助私有(private)构造函数,该构造函数也采用虚拟参数。如果其他参数不满足某些条件,虚拟参数允许 SFINAE 忽略构造函数。

所以我的问题是:

1) 这是一个可以接受的解决方案吗?还是我只是幸运,GCC 将我委托(delegate)给的私有(private)构造函数视为公共(public)构造函数重载决议的一部分?

2) 有更简洁的方法吗?

我搜索并找到了类似问题的答案,但我找到的答案是在函数而非构造函数上实现的。他们在返回类型上使用 enable_if 来强制编译器从重载决议表中排除该函数。

最佳答案

重载解析不考虑可访问性;该检查稍后完成。

你所做的实际上不是 SFINAE;它不影响重载决议,只会使模板构造函数的实例化在被重载决议选择后格式错误。

我们可以通过添加一个不太匹配的非模板构造函数来看到这一点:

template< class T >
class myobject
{
/* ... */
public:

/* ... */
myobject( const char * ptr )
{
std::cout << "const char * constructor" << std::endl;
}

template< typename... Ts >
myobject( Ts... params )
: myobject( typename CheckVaradicArgs<Ts...>::type(), params... )
{
std::cout << "Ts constructor with " << sizeof...(params) << std::endl;
}

};

char * p = nullptr;
myobject<int> something(p);

如果是 SFINAE,模板将被排除在重载决策之外,并选择 const char * 构造函数。相反,你得到一个 compile error因为编译器试图实例化可变参数模板 (g++ does the same thing )。

对于SFINAE,只需添加一个额外的模板参数:

template< class T >
class myobject
{

template< typename... Ts >
using CheckVariadicArgs =
typename std::enable_if<
all_true< std::is_convertible<Ts, T>... >::value, int
>::type;
public:

myobject( const myobject& other )
{
std::cout << "Copy constructor" << std::endl;
}

template< typename... Ts, CheckVariadicArgs<Ts...>* = nullptr >
myobject( Ts... params )
{
std::cout << "Ts constructor with " << sizeof...(params) << std::endl;
}

};

Demo .

关于c++ - 在构造函数中限制可变参数模板的可接受方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25274543/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com