问题描述
假设我想让一个变量持有一个非常复杂的类型的值,并且编译器会自动推断出它的类型,但是由于在if语句中进行了初始化,因此在代码中先声明然后给出值。 / p>
例如:
{
auto a;
if (some predicate)
a = init_a(1);
else
a = init_a(2);
}
显然,此代码无法编译,但是我认为编译器具有推断类型的所有信息。
如果'a'只是一个int,这不是问题,但是如果类型是一个复杂的模板,我就不必编写它(或者在某些情况下甚至知道它)。 另外,我不想调用a的默认构造函数,然后覆盖它。
可能的解决方案:
- 模板“ a”的类型。
- 使用lambda初始化“ a”,然后将谓词移至lambda。
- 只写'a'的类型而不是自动。
- 使用void指针/ shared_ptr,然后在堆上初始化“ a”。
每一个都有其自身的缺点。
是否有更优雅的解决方案?
解决方法
编译器没有无限的前瞻性,代码中将进一步发生什么。它只知道当前语句正在发生什么。因此,没有初始化程序就无法推断出任何类型。
如果您不知道init_a
的返回类型,则可以使用decltype
:
decltype(init_a(1)) a;
您还可以使用lambda调用来初始化变量:
auto a = [ /* Captures needed for the condition... */ ]()
{
if (some_condition)
return init_a(1);
else
return init_a(2);
}(); // Call the lambda immediately
或者,如许多评论中所述,使用三元条件表达式:
auto a = some_condition ? init_a(1) : init_a(2);
,
有一种称为“立即调用Lambda表达式”的技术,该技术使用lambda以复杂的方式初始化变量。使用这种方法,您的a
可以是const,从而提高const正确性。 More details here。
对于简单的二进制谓词,请考虑仅使用三元运算符:
_controller1.addListener(() {
_controller2.animateToPage(
_controller1.page.toInt(),duration: Duration(milliseconds: 500),curve: Curves.ease,);
});
对于更复杂的初始化逻辑(除了二进制情况),请将初始化逻辑包装在lambda中:
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255,18,32,47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),debugShowCheckedModeBanner: false,home: Scaffold(
body: Center(
child: MyPageControllers(),),);
}
}
class MyPageControllers extends StatefulWidget {
@override
_MyPageControllersState createState() => _MyPageControllersState();
}
class _MyPageControllersState extends State<MyPageControllers> {
PageController _controller1;
PageController _controller2;
int manualController = -1;
Widget _itemBuilder(BuildContext context,int index) => Container(
color: Colors.primaries[index % Colors.primaries.length],child: Center(
child: Text(
index.toString(),style: TextStyle(color: Colors.white,fontSize: 60),);
@override
void initState() {
super.initState();
_controller1 = PageController(viewportFraction: 0.8);
_controller2 = PageController(viewportFraction: 0.5);
_controller1.addListener(() {
if (manualController == 1) {
_controller2.jumpTo(_controller1.offset);
}
});
_controller2.addListener(() {
if (manualController == 2) {
_controller1.jumpTo(_controller2.offset);
}
});
// _controller1.addListener(() {
// _controller2.animateToPage(
// _controller1.page.toInt(),// duration: Duration(milliseconds: 500),// curve: Curves.ease,// );
// });
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: GestureDetector(
onTapDown: (tapDownDetails){
manualController = 1;
setState(() {});
},onTapUp: (tapUpDetails){
manualController = -1;
setState(() {});
},child: PageView.builder(
controller: _controller1,itemBuilder: _itemBuilder,SizedBox(
height: 40,Expanded(
child: GestureDetector(
onTapDown: (tapDownDetails){
manualController = 2;
setState(() {});
},child: PageView.builder(
controller: _controller2,],);
}
}
这两种方法都带有将变量初始化为 TypeError: animationBuilder is not a function
at animation (index-96111fa9.js:72)
的可能性。