Как сгладить список опций, используя функции высшего порядка?

not необходимо поместить реализацию в файл заголовка, см. альтернативное решение в конце этого ответа.

В любом случае причина, по которой ваш код не работает, что при создании экземпляра шаблона компилятор создает новый класс с заданным аргументом шаблона. Например:

template
struct Foo
{
    T bar;
    void doSomething(T param) {/* do stuff using T */}
};

// somewhere in a .cpp
Foo f; 

При чтении этой строки компилятор создаст новый класс (назовем его FooInt), что эквивалентно следующему:

struct FooInt
{
    int bar;
    void doSomething(int param) {/* do stuff using int */}
}

Следовательно, компилятор должен иметь доступ к реализации методов, чтобы создать экземпляр с аргументом шаблона (в данном случае int). Если эти реализации не были в заголовке, они не были бы доступны, поэтому компилятор не смог бы создать экземпляр шаблона.

Общим решением для этого является запись объявления шаблона в заголовок файла, затем реализовать класс в файле реализации (например, .tpp) и включить этот файл реализации в конец заголовка.

// Foo.h
template 
struct Foo
{
    void doSomething(T param);
};

#include "Foo.tpp"

// Foo.tpp
template 
void Foo::doSomething(T param)
{
    //implementation
}

Таким образом, реализация по-прежнему отделена от объявления, но доступен компилятору.

Другое решение состоит в том, чтобы сохранить реализацию отдельно и явно создать все экземпляры шаблона, которые вам понадобятся:

// Foo.h

// no implementation
template  struct Foo { ... };

//----------------------------------------    
// Foo.cpp

// implementation of Foo's methods

// explicit instantiations
template class Foo;
template class Foo;
// You will only be able to use Foo with int or float

Если мое объяснение isn ' t достаточно ясно, вы можете взглянуть на C ++ Super-FAQ по этому вопросу .

34
задан giampaolo 13 February 2014 в 21:10
поделиться

2 ответа

В Scala 2.8 flatten будет работать:


Welcome to Scala version 2.8.0.RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val listOfOptions = List(None, Some("hi"), None)
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None)

scala> listOfOptions flatten
res0: List[java.lang.String] = List(hi)

Это не работает в 2.7.7, однако:


Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).

scala> val listOfOptions = List(None, Some("hi"), None)
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None)

scala> listOfOptions.flatten
:6: error: no implicit argument matching parameter type (Option[java.lang.String]) => Iterable[Nothing] was found.
       listOfOptions.flatten

Библиотека коллекций была переработана и значительно улучшена в 2.8, так что, возможно, вы захотите попробуйте использовать последнюю версию Scala 2.8 RC и посмотрите, упростит ли это использование.

Если вы действительно не хотите использовать метод toList, я думаю, вы также можете написать его так:


scala> listOfOptions.flatMap(o => o)
res: List[java.lang.String] = List(hi)

Возможно, тоже не очень красиво, но, по крайней мере, это работает в 2.7.7.

53
ответ дан 27 November 2019 в 16:33
поделиться

В дополнение к ответу Арьяна в Scala 2.7.7 вы можете использовать List # flatten , но вам нужно помочь в выводе типов:

Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val listOfOptions = List(None, Some("hi"), None)
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None)

scala> listOfOptions.flatten[String]                   
res0: List[String] = List(hi)

scala> val x: List[String] = listOfOptions.flatten
x: List[String] = List(hi)
19
ответ дан 27 November 2019 в 16:33
поделиться
Другие вопросы по тегам:

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