请考虑以下示例代码:
#include <tuple>
void blah();
int buh;
constexpr auto get()
{
return std::get<0>(std::make_tuple(&blah, &buh));
}
int main()
{
get();
}
可以预期,因为函数get()
是一个常量表达式,它将返回一个常量。
不是这样:std::make_tuple
,std::get
被实例化并被调用:https://godbolt.org/g/PkHrTp
现在,如果我们用
替换get()
的实现
constexpr auto get()
{
constexpr auto x = std::get<0>(std::make_tuple(&blah, &buh));
return x;
}
我们得到预期的行为:参数x
的计算已经优化,即使在-O0,make_tuple
,get
也没有实例化,这对于减少二元膨胀。
是否有一种惯用的方式来强制constexpr auto foo()
形式的函数总是像第二个示例中那样?
现在我会诉诸:
#define constexpr_return(X) do { constexpr auto constexpr_return_x_ = X; return constexpr_return_x_; } while(0)
constexpr_return(std::get<0>(std::make_tuple(&blah, &buh)));
例如但我不知道这是否是最佳的。
答案 0 :(得分:2)
<Window x:Class="ObservableStackBug.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="Add" Margin="5" Padding="8 2" HorizontalAlignment="Left" Click="ButtonBase_OnClick"/>
<ListBox ItemsSource="{Binding StateStack}" Grid.Row="1" />
<TabControl Grid.Row="2" ItemsSource="{Binding Men}" SelectedIndex="{Binding DebugIndex}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Index}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
</Grid>
</Window>
实际上必须在编译时评估非类型模板参数。
template<auto x>
std::integral_constant< std::decay_t<decltype(x)>, x > k{};
或在某些极端情况下k<get()>
可能会执行您想要的操作。
对于不能作为非类型模板参数传递的k<get()>()
值,这不起作用,但它适用于整数,指针和函数指针。