【问题标题】:auto type deduction for argument with default value具有默认值的参数的自动类型推导
【发布时间】:2017-09-24 09:42:00
【问题描述】:

对于没有足够的时间进行深入调查并依靠您的帮助,我深表歉意。

考虑一下简单的代码:

#include <iostream>

enum class PrintColour
{
    COLOUR_1        =   0,
    COLOUR_2        =   1,
};
 
void colour( auto c = PrintColour::COLOUR_1 )
{
    switch ( c )
    {
        case PrintColour::COLOUR_1:
            std::cout << "Colour 1" << std::endl;
            break;
        case PrintColour::COLOUR_2:
            std::cout << "Colour 2" << std::endl;
    }
}

int main( )
{
//  colour( ); couldn't deduce template parameter ‘auto:1’
    colour( PrintColour::COLOUR_1 );    // Fine!
}

此代码完全按原样编译和运行,没有问题。但是,如果我取消注释 colour( );,g++ 会触发错误:

auto_param.cpp: In function ‘int main()’:
auto_param.cpp:27:10: error: no matching function for call to ‘colour()’
  colour( );
          ^
auto_param.cpp:13:6: note: candidate: template<class auto:1> void colour(auto:1)
 void colour( auto c = PrintColour::COLOUR_1 )
      ^~~~~~
auto_param.cpp:13:6: note:   template argument deduction/substitution failed:
auto_param.cpp:27:10: note:   couldn't deduce template parameter ‘auto:1’
  colour( );
          ^

可能我只是忽略了一个愚蠢的观点,或者我可能真的很愚蠢并且误解了整个事情。

我是否应该能够将函数参数声明为 auto,同时仍然能够在 C++11 或 C++14 中为其赋予默认值?

我认为给定的默认值足以让编译器推断出参数类型...


编辑 1:

它认为我需要让我的问题更清楚,以免被Is there a way to pass auto as an argument in C++?弄错

这里的重点不是将auto 传递给函数,而是将auto 与参数的默认值结合使用,上述问题中没有考虑到这一点。

编辑 2:

正如 cmets here 中所阐明的,C++11 没有将auto 作为参数传递的功能,但 C++14 及更高版本(g++ 6.3.1 默认为“gnu++14”)似乎.不过,我最初的问题与 C++11 无关,我的问题不是 C++11 是否支持 auto 参数。我依赖auto 作为参数,但忘记仔细检查它的最低标准版本。很抱歉,我现在解决了这个问题。

g++ -std=c++11 auto_param.cpp -o auto_param
auto_param.cpp:13:14: error: use of ‘auto’ in parameter declaration only available with -std=c++14 or -std=gnu++14

我希望清楚我的问题和Is auto as a parameter in a regular function a GCC 4.9 extension? 之间的区别。如果没有请告诉我。

【问题讨论】:

标签: c++ c++14 default-value auto


【解决方案1】:

不,it is a non-deduced context

非推断上下文

在以下情况下,类型、模板和 用于组成 P 的非类型值不参与 模板参数推导,而是使用模板参数 在别处推导出来或明确指定。如果一个 模板参数仅在非推导上下文中使用,而不是 明确指定,模板参数推导失败。

<...>

4) 一个 函数形参的形参类型中使用的模板形参 具有在调用中使用的默认参数 正在推论中

【讨论】:

  • 你说的是模板参数推导。 OP正在询问auto的扣除。
  • @R Sahu "auto" 参数的类型推导(在 mini-concepts TS 中定义)与模板参数的类型推导有何不同?
  • auto 函数参数的类型在 C++11 中不受支持。它仅支持 C++14 中的 lambda 函数。有一个提议在 C++17 中支持它。我没有看到那个提议。我不知道模板参数推导有多相似。在处理 C++11 或 C++14 时,我们甚至无法进行有意义的讨论。
  • 据我所知,void foo(auto a) 旨在与template &lt;class T&gt; void foo(T a) 相同。
  • @fljx 是here 参见 7.1.6.4:“同样,如果占位符出现在函数声明的参数类型中,则函数声明声明了一个缩写函数模板”
【解决方案2】:

我是否应该能够在 C++11 或 C++14 中将函数参数声明为 auto 同时仍然能够为其赋予默认值?

我不知道 C++17 是否支持它,但据我所知,C++11 和 C++14 不支持函数的 auto 参数(C++14 支持它仅适用于 lambda 函数)

我认为给定的默认值足以让编译器推断出参数类型...

如果您接受使用模板类型而不是 auto,则还必须添加默认模板类型。

如下

template <typename T = decltype(PrintColour::COLOUR_1)>
void colour( T c = PrintColour::COLOUR_1 )
{
    switch ( c )
    {
        case PrintColour::COLOUR_1:
            std::cout << "Colour 1" << std::endl;
            break;
        case PrintColour::COLOUR_2:
            std::cout << "Colour 2" << std::endl;
    }
}

我知道:是多余的。

-- 编辑--

OP 说

我只是想知道我是否不能通过不重复来使我的代码更具可读性

可能不是更具可读性,但是...如果您不希望它重复...我知道宏是邪恶的,但是...如果您真的想要避免重复...

#define noRepeat(r, n, a, b) \
r n (decltype(b) a = b)

noRepeat(void, colour, c, PrintColour::COLOUR_1)
{
    switch ( c )
    {
        case PrintColour::COLOUR_1:
            std::cout << "Colour 1" << std::endl;
            break;
        case PrintColour::COLOUR_2:
            std::cout << "Colour 2" << std::endl;
    }
}

或者也(如果你想在参数的基础上制作技巧)

#define parDef(a, b)  decltype(b) a = b

void colour ( parDef(c, PrintColour::COLOUR_1), parDef(d, 5) )
{
    switch ( c )
    {
        case PrintColour::COLOUR_1:
            std::cout << "Colour 1" << std::endl;
            break;
        case PrintColour::COLOUR_2:
            std::cout << "Colour 2" << std::endl;
    }
}

【讨论】:

  • 谢谢@max66。我只是想知道是否不能通过不重复 ( PrintColour c = PrintColour::COLOUR_1 ) 来使我的代码更具可读性。我知道它不起作用,但我仍然想了解原因(并且可能还学习另一种整理代码的方法)。正如@Igor R. 的评论,我认为auto 是“语法糖”。
  • @fljx - 我明白了......好吧......如果你想避免重复......答案改进了。
  • 您的编辑很诱人...我正在考虑类似#define def_deduce( p, def_value ) decltype( def_value ) p = def_value 和后来的void colour( def_deduce( c, PrintColour::COLOUR_1 ) ) 但是,正如您所说。宏是可耻的。最后说明,根据g++,好像C++14支持auto作为参数。
  • @fljx - 如果你忘记了-pedantic,g++ 接受auto;使用-pedantic 你会得到一个错误; C++14 仅接受 auto 用于 lambda 函数(据我所知),但如果您尝试类似 auto colour = [](auto c = PrintColour::COLOUR_1) { }; 的操作,则在您调用 colour( PrintColour::COLOUR_1 ); 时有效,但当您调用 colour(); 时,您会收到类似于 @987654338 的错误@(clang++ 和 g++)。
猜你喜欢
  • 1970-01-01
  • 2018-05-26
  • 1970-01-01
  • 1970-01-01
  • 2019-01-09
  • 1970-01-01
  • 2021-09-21
  • 2018-02-18
  • 2021-12-22
相关资源
最近更新 更多