如何' std::initializer_list '值通过编译器?(或者:我怎样才能避免一个普遍的超载?)
How are `std::initializer_list` values passed by the compiler? (Or: how can I get around a universal overload with one?)
继续我的故事,我已经意识到我可以重载我的访问函数,使用单个std::initializer_list
参数代替:
class array_md
{
//...
my_type & operator []( size_type i )
{ /* Lots of code */ }
my_type const & operator []( size_type i ) const
{ /* same Lots of code, with "const" sprinkled in */ }
my_type & operator []( std::initializer_list<size_type> i )
{ /* Lots of different code */ }
my_type const & operator []( std::initializer_list<size_type> i ) const
{ /* same Lots of different code, with "const" sprinkled in */ }
//...
};
对于我的at
版本我现在有:
class array_md
{
//...
template < typename ...Index >
complicated & at( Index &&...i ) // (1)
{ /* Lots of code */ }
template < typename ...Index >
complicated const & at( Index &&...i ) const // (2)
{ /* same Lots of code, with "const" sprinkled in */ }
my_type & at( std::initializer_list<size_type> i ) // (3)
{ /* Lots of different code */ }
my_type const & at( std::initializer_list<size_type> i ) const // (4)
{ /* same Lots of different code, with "const" sprinkled in */ }
//...
};
(由于不能根据初始化器列表中的条目数量更改类型,因为它是运行时的,所以我修复了返回类型,如果条目数量错误则抛出。)新的重载代码很长,我必须为mutable
和const
版本重复它,所以我想知道如何保存代码。我试着修改const_cast
:
class array_md
{
//...
my_type & operator []( size_type i );
my_type const & operator []( size_type i ) const;
my_type & operator []( std::initializer_list<size_type> i )
{
return const_cast<my_type &>( const_cast<array_md const
*>(this)->operator [](i) );
}
my_type const & operator []( std::initializer_list<size_type> i ) const;
//...
};
这里第三个版本调用第四个版本,使用const_cast
来避免编译器的投诉。(侵入是可以的,因为我剥离const
从我打了它开始。不要反转依赖关系;你最终可能会在一个真正的const
对象上调用mutable
成员函数!)我试图为at
做同样的事情,用标记为(4)的重载实现标记为(3)的重载。然而,由于at
有三个替代方案,我得到了与(2)相关的错误。是否有一些我如何传递std::initializer_list
到内部at
调用(按值),这不会导致与通用过载相比的精确匹配?我是通用方法冲突的老朋友。
TL;DR:示例代码显示std::initializer_list
对象在函数参数列表中按值获取。这是编译器在传递它们时的首选项吗?还是通过引用?如果您需要精确匹配(以克服通用重载),这一点很重要。
消歧强制转换:
int f( int );
double f( double );
template < typename Func, typename ...Args >
void do_it( Func &&f, Args &&...a );
//...
int main( int, char *[] )
{
do_it( (double(*)(double))&f, 5.4 );
return 0;
}
main
中的代码强制使用f
的第二个版本。我以为这个能力是C-cast独有的,但它在static_cast
下。所以我得到了这样的东西:
class array_md
{
//...
template < typename ...Index >
complicated & at( Index &&...i ); // (1)
template < typename ...Index >
complicated const & at( Index &&...i ) const; // (2)
my_type & at( std::initializer_list<size_type> i ) // (3)
{
return const_cast<my_type &>(
(
const_cast<array_md const *>( this )
->*
static_cast<
my_type const &
(array_md::*)
( std::initializer_list<size_type> ) const
>( &array_md::at )
)( i )
);
}
my_type const & at( std::initializer_list<size_type> i ) const; // (4)
//...
};
(我得到了我的灵感,通过回答别人的帖子需要区分函数模板重载。)这需要进行几次尝试,特别是没有创建中间对象。
相关文章:
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 你能把一个向量<int64>投射到一个向量<uint8>吗
- 为什么我不能创建一个 TSubclassOf<> 在 SpawnActor() 函数中使用?
- 为什么我不能声明一个 constexpr 本地,而一个 const 一个工作?
- 我怎么能有一个以2D数组为参数的函数,而数组有一个我想更改的参数/维度
- 你能pop_back一个向量,并且仍然使用迭代器到最后一个元素吗?
- 为什么我不能提供一个字符串参数来打印 ncurses?
- 为什么我不能为一个 asio io_service使用两个计时器?
- 你能把一个指针投射到数组中吗?
- 指针怎么能有一个字符串作为它的值
- OpenGL不能成为一个完美的立方体
- 不能在一个qlist中添加多个结构
- 我怎么能写一个长度函数来返回间隔的长度
- 你能把一个工会成员的值分配给另一个吗
- 你能把一个额外的参数传递给谓词吗?
- 为什么本地人总是能得到一个公平的地址
- 为什么我不能将一个 Xalan 类的static_cast使用到它的基类?
- 为什么 g++ 不能编译一个简单的 GTK 程序?
- 当我在类中声明一个固定长度的向量时,我能避免歧义吗?