At one of my project usage temporary tables with indexes at several columns and with option adding new columns to them was quite critical to for me. (ALTER TABLE is also not supported for temp tables). The standard table was not the option as each query run had to have own table.
Finally, I used something that can be used as temporary tables but in fact is not a temporary table. I'm creating a standard table but with Guid as name and assign the name to a variable. So instead of #TempTable I'm using @MySemiTempTable but that work only for generated code. So I have to run that code using sp_executesql. Bellow example:
declare @MySemiTempTable NVARCHAR(MAX)
declare @sql NVARCHAR(MAX)
set @MySemiTempTable = 'TMP_' + CAST(NEWID () AS NVARCHAR(37))
set @sql = 'CREATE TABLE ['+ @MySemiTempTable + '] (Column1 [int], Column2 NVARCHAR(50))'
EXECUTE sp_executesql @sql
set @sql = 'INSERT INTO ['+ @MySemiTempTable + '] VALUES (1, ''test1'')'
EXECUTE sp_executesql @sql
set @sql = 'create unique index column1 on ['+ @MySemiTempTable + '] (column1)'
EXECUTE sp_executesql @sql
set @sql = 'select * from ['+ @MySemiTempTable + '] '
EXECUTE sp_executesql @sql
set @sql = 'drop table ['+ @MySemiTempTable + '] '
EXECUTE sp_executesql @sql