Использование лямбды вместо индексного параметра шаблона

Ниже приведена ситуация, с которой я столкнулся, используя переменные таблицы.

DECLARE @Object_Table TABLE
(
    Id INT NOT NULL PRIMARY KEY
)

DECLARE @Link_Table TABLE
(
    ObjectId INT NOT NULL,
    DataId INT NOT NULL
)

DECLARE @Data_Table TABLE
(
    Id INT NOT NULL Identity(1,1),
    Data VARCHAR(50) NOT NULL
)

-- create two objects '1' and '2'
INSERT INTO @Object_Table (Id) VALUES (1)
INSERT INTO @Object_Table (Id) VALUES (2)

-- create some data
INSERT INTO @Data_Table (Data) VALUES ('Data One')
INSERT INTO @Data_Table (Data) VALUES ('Data Two')

-- link all data to first object
INSERT INTO @Link_Table (ObjectId, DataId)
SELECT Objects.Id, Data.Id
FROM @Object_Table AS Objects, @Data_Table AS Data
WHERE Objects.Id = 1

Благодаря другому ответу , который указал мне на предложение OUTPUT, я могу продемонстрировать решение:

-- now I want to copy the data from from object 1 to object 2 without looping
INSERT INTO @Data_Table (Data)
OUTPUT 2, INSERTED.Id INTO @Link_Table (ObjectId, DataId)
SELECT Data.Data
FROM @Data_Table AS Data INNER JOIN @Link_Table AS Link ON Data.Id = Link.DataId
                INNER JOIN @Object_Table AS Objects ON Link.ObjectId = Objects.Id 
WHERE Objects.Id = 1

Оказывается, однако, что это не так просто в реальной жизни из-за следующей ошибки

, предложение OUTPUT INTO не может быть по обе стороны от ( первичный ключ, внешний ключ)

blockquote>

Я все еще могу OUTPUT INTO создать таблицу temp, а затем закончить с обычной вставкой. Поэтому я могу избежать цикла, но я не могу избежать таблицы temp.

1
задан dlasalle 19 March 2019 в 17:00
поделиться

2 ответа

template<class F>
struct square_bracket_invoke_t {
  F f;
  template<class T>
  auto operator[](T&& t)const
  -> typename std::result_of< F const&(T&&) >::type
  { return f(std::forward<T>(t)); }
};
template<class F>
square_bracket_invoke_t< typename std::decay<F>::type >
make_square_bracket_invoke( F&& f ) {
  return {std::forward<F>(f)};
}

Живой пример .

Код - это C ++ 11, и в нем практически нет накладных расходов.

int main() {
  std::cout << foo( 6, make_square_bracket_invoke([](int x){ return x; } ) ) << "\n";
}

результат равен 0 + 1 + 2 + 3 + 4 + 5 или 15.

Это хорошая идея? Может быть. Но зачем останавливаться на достигнутом?

Для максимального удовольствия:

const auto idx_is = make_square_bracket_invoke([](auto&&f){return make_square_bracket_invoke(decltype(f)(f));});
int main() {
  std::cout << foo( 6, idx_is[[](int x){ return x; }] ) << "\n";
}
0
ответ дан Yakk - Adam Nevraumont 19 March 2019 в 17:00
поделиться

Ну, если это поможет, вот способ переслать класс-обертку operator[] к вашей лямбде operator().

template<class F>
struct SubscriptWrapper_t {
  F f_;
  template<class T> auto operator[](T const& t_) const -> decltype(f_(t_)) { 
    return f_(t_); 
  }
};
template<class F> 
SubscriptWrapper_t<typename std::decay<F>::type> SubscriptWrapper(F&& f_) {
  return{std::forward<F>(f_)}; 
}

Я часто использую такие обертки. Они удобны, и у них, похоже, нет вычислительных затрат, по крайней мере, при компиляции GCC. Вы можете сделать один для at или даже сделать для find.

РЕДАКТИРОВАТЬ: Обновлено для C ++ 11 (и обновлено, чтобы иметь возможность возвращать ссылку)

0
ответ дан hegel5000 19 March 2019 в 17:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: