没有定义的自动变量声明

问题描述

我想知道以下问题是否有一个优雅的解决方案:

假设我想让一个变量持有一个非常复杂的类型的值,并且编译器会自动推断出它的类型,但是由于在if语句中进行了初始化,因此在代码中先声明然后给出值。 / p>

例如:

{
  auto a;
  if (some predicate)
      a = init_a(1);
  else
      a = init_a(2);
}

显然,此代码无法编译,但是我认为编译器具有推断类型的所有信息。

如果'a'只是一个int,这不是问题,但是如果类型是一个复杂的模板,我就不必编写它(或者在某些情况下甚至知道它)。 另外,我不想调用a的认构造函数,然后覆盖它。

可能的解决方案:

  1. 模板“ a”的类型。
  2. 使用lambda初始化“ a”,然后将谓词移至lambda。
  3. 只写'a'的类型而不是自动
  4. 使用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) 的可能性。