И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 11:27
Оценка: 1 (1)
Требуется сделать явное инстанциирование шаблонной функции, у которой параметр задаётся через traits. Сложно на словах объяснить, в общем код:


// Структура задаёт тип параметра, который принимает конструктор
template<typename Type>
struct ParamTraits
{
typedef Type ParamType;
};

// Специализация для строки
template<>
struct ParamTraits<std::string>
{
typedef const std::string& ParamType;
};

// Основной класс
class Test
{
public:
// Шаблонный конструктор
// принимает параметр типа, который определяется ParamTraits
template<typename Type>
Test(typename ParamTraits<Type>::ParamType param);
};

// Реализация конструктора
template<typename Type>
Test::Test(typename ParamTraits<Type>::ParamType param)
{
// ...
}

// Инстанциирование
#define INSTANTIATE_TEST(Type) template Test::Test(ParamTraits<Type>::ParamType)

INSTANTIATE_TEST(int);
INSTANTIATE_TEST(long);
INSTANTIATE_TEST(std::string);


При компиляции инстанциирования компилятор (msvc7.1) 3 раза (для каждого инстанциирования) выдаёт:
error C2945: explicit instantiation does not refer to a template-class specialization
error C3190: 'Test::Test(ParamTraits<Type>::ParamType)' with the provided template arguments is not the explicit instantiation of any member function of 'Test'

Как правильно записать такое инстанциирование?

Заранее спасибо за ответы.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: И опять синтаксис шаблонов...
От: swamper  
Дата: 03.10.05 11:58
Оценка: 2 (1)
>> Здравствуйте, remark, Вы писали:

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

#define INSTANTIATE_TEST(Type)        \
  template<typename T> struct dummy;  \
  template<> struct dummy<Type> { Test test(ParamTraits<Type>::ParamType()); }
Re: И опять синтаксис шаблонов...
От: Глеб Алексеев  
Дата: 03.10.05 12:09
Оценка: 5 (1)
Здравствуйте, remark, Вы писали:

R>// Инстанциирование

R>#define INSTANTIATE_TEST(Type) template Test::Test(ParamTraits<Type>::ParamType)

R>INSTANTIATE_TEST(int);

R>INSTANTIATE_TEST(long);
R>INSTANTIATE_TEST(std::string);
В твоем коде тип Type невозможно вывести из ParamTraits<Type>::ParamType. Поэтому макрос INSTANTIATE_TEST должен был бы выглядеть так:
#define INSTANTIATE_TEST(Type) template Test::Test<Test>(ParamTraits<Type>::ParamType)

Но! Не тут-то было. У ВЦ 7.1, как оказалось благодаря твоему вопросу ( ), проблемы с явным инстанцированием конструкторов:
struct A {
  template <class T> A() {
  }
  template <class T> void f() {
  }
};

template A::A<int>();      //VC видит здесь syntax error
template void A::f<int>(); //компилится

Как быть? Сделать аргументы шаблона выводимыми:
struct A {
  template <class T> A(T* dummy=0) {
  }
};

template A::A(int*);


Для своего случая доделаешь сам.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: опечатка, конечно
От: Глеб Алексеев  
Дата: 03.10.05 12:11
Оценка:
ГА>
ГА>#define INSTANTIATE_TEST(Type) template Test::Test<Type>(ParamTraits<Type>::ParamType)
ГА>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 12:29
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>В твоем коде тип Type невозможно вывести из ParamTraits<Type>::ParamType.


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


template<typename Type>
struct S
{};

template<typename Type>
void func(S<Type> s)
{
    std::cout << typeid(Type).name();
}

S<float> obj;
func(obj);

template void func(S<int>);



ГА>Поэтому макрос INSTANTIATE_TEST должен был бы выглядеть так:

ГА>
ГА>#define INSTANTIATE_TEST(Type) template Test::Test<Test>(ParamTraits<Type>::ParamType)
ГА>

ГА>Но! Не тут-то было. У ВЦ 7.1, как оказалось благодаря твоему вопросу ( ), проблемы с явным инстанцированием конструкторов:
ГА>
ГА>struct A {
ГА>  template <class T> A() {
ГА>  }
ГА>  template <class T> void f() {
ГА>  }
ГА>};

ГА>template A::A<int>();      //VC видит здесь syntax error
ГА>template void A::f<int>(); //компилится
ГА>

ГА>Как быть? Сделать аргументы шаблона выводимыми:
ГА>
ГА>struct A {
ГА>  template <class T> A(T* dummy=0) {
ГА>  }
ГА>};

ГА>template A::A(int*);
ГА>


ГА>Для своего случая доделаешь сам.


Было бы всё так просто, я бы не стал звать тех. поддержку

Сделал так:

template<typename Type>
Test(typename ParamTraits<Type>::ParamType param, Type* p = 0);

// Реализация конструктора
template<typename Type>
Test::Test(typename ParamTraits<Type>::ParamType param, Type*)
{
    // ...
}


// Инстанциирование
#define INSTANTIATE_TEST(Type) template Test::Test(ParamTraits<Type>::ParamType, Type*)


INSTANTIATE_TEST(int);
INSTANTIATE_TEST(long);
INSTANTIATE_TEST(std::string);



Те же самые ошибки!

Тут, по-моему, проблема именно с ParamTraits<Type>::ParamType.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: И опять синтаксис шаблонов...
От: __LP  
Дата: 03.10.05 12:36
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Глеб Алексеев, Вы писали:


ГА>>В твоем коде тип Type невозможно вывести из ParamTraits<Type>::ParamType.


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



R>
R>template<typename Type>
R>struct S
R>{};

R>template<typename Type>
R>void func(S<Type> s)
R>{
R>    std::cout << typeid(Type).name();
R>}

R>S<float> obj;
R>func(obj);

R>template void func(S<int>);
R>


Параметр шаблона не выводится если он в квалификаторе ParamTraits<Type>::ParamType

PS А разве можно делать сразу и явное инст-ие и явную специализацию
C++ можно выучить за 21 день! ...если дни — полярные.
Re[2]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 03.10.05 12:37
Оценка: 8 (1)
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Но! Не тут-то было. У ВЦ 7.1, как оказалось благодаря твоему вопросу ( ), проблемы с явным инстанцированием конструкторов:


И не только у него. GCC 3.4.2 (и 4.0 также) плохо реагирует на явное инстанцирование конструктора, когда тип указывается явно:
class A
{
public:
    template <typename Type>
    A(Type ) {}

    template <typename Type>
    void foo(Type ) {}
};

template A::A(int ); // Вот так все ОК
template A::A<long>(long ); // А вот так уже плохо.

// А здесь всегда все хорошо
template void A::foo(int );
template void A::foo<long>(long );


На высоте себя показали Intel C++ и Comeau — оба ведут себя хорошо.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[3]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 03.10.05 12:41
Оценка:
Здравствуйте, remark, Вы писали:

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


R>
R>template<typename Type>
R>struct S
R>{};

R>template<typename Type>
R>void func(S<Type> s)
R>{
R>    std::cout << typeid(Type).name();
R>}

R>S<float> obj;
R>func(obj);

R>template void func(S<int>);
R>


Нет, в первоначальном варианте использовалось dependent name ParamTraits<Type>::ParamType, а по нему правильный ParamTraits автоматически вывести нельзя.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 12:51
Оценка:
Здравствуйте, swamper, Вы писали:

>>> Здравствуйте, remark, Вы писали:


S>А зачем нужно инстанцирование? Не совсем понятно, какой от этого будет толк.

S>Тем не менее, вот пример кода, который инстанцирует шаблонную функцию:

S>
S>#define INSTANTIATE_TEST(Type)        \
S>  template<typename T> struct dummy;  \
S>  template<> struct dummy<Type> { Test test(ParamTraits<Type>::ParamType()); }
S>



Интересный вариант. Не делать явное инстанциирование, а заставить компилятор инстанциировать.
Тут есть ограничение, что ParamTraits<Type>::ParamType должен иметь конструктор по-умолчанию, но в моём случае, это не страшно.

Хотя так всё равно не работает. Компилятор не инстанциирует шаблон.
Я написал что-то вроде этого:

#define INSTANTIATE_TEST(Type)        \
  template<typename T> struct dummy;  \
  template<> struct dummy<Type> { dummy() {Test test(ParamTraits<Type>::ParamType());} };    \
  void func##Type ()    \
    {dummy<Type> dummy;};


Теперь шаблон инстанциируется.


Но, при компиляции:

Test test(10);


ругается:

error C2664: 'Test::Test(const Test &)' : cannot convert parameter 1 from 'int' to 'const Test &'

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 12:54
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX>Здравствуйте, remark, Вы писали:


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


R>>
R>>template<typename Type>
R>>struct S
R>>{};

R>>template<typename Type>
R>>void func(S<Type> s)
R>>{
R>>    std::cout << typeid(Type).name();
R>>}

R>>S<float> obj;
R>>func(obj);

R>>template void func(S<int>);
R>>


CX>Нет, в первоначальном варианте использовалось dependent name ParamTraits<Type>::ParamType, а по нему правильный ParamTraits автоматически вывести нельзя.


Вывести надо Type, а не ParamType. Хотя я тут не очень силён.
Ну ладно, это не важно. Всё равно решения не получается.

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 12:55
Оценка:
Здравствуйте, __LP, Вы писали:

__L>Здравствуйте, remark, Вы писали:


R>>Здравствуйте, Глеб Алексеев, Вы писали:


ГА>>>В твоем коде тип Type невозможно вывести из ParamTraits<Type>::ParamType.


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



R>>
R>>template<typename Type>
R>>struct S
R>>{};

R>>template<typename Type>
R>>void func(S<Type> s)
R>>{
R>>    std::cout << typeid(Type).name();
R>>}

R>>S<float> obj;
R>>func(obj);

R>>template void func(S<int>);
R>>


__L>Параметр шаблона не выводится если он в квалификаторе ParamTraits<Type>::ParamType


Возможно, я тут не очень силён.

__L>PS А разве можно делать сразу и явное инст-ие и явную специализацию


По стандарту нельзя. Но я же не делал специализаций шаблона.

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 03.10.05 13:00
Оценка:
Здравствуйте, remark, Вы писали:

R>Вывести надо Type, а не ParamType. Хотя я тут не очень силён.

R>Ну ладно, это не важно. Всё равно решения не получается.

Хмм... Так тебе ParamTraits не нужен в конструкторе? Тогда может так подойдет:
// Основной класс
class Test
{
public:
    // Шаблонный конструктор
    // принимает параметр типа, который определяется ParamTraits
    template<typename Type>
    Test(Type param);
};

// Реализация конструктора
template<typename Type>
Test::Test(Type param)
{
// ...
}

// Инстанциирование
#define INSTANTIATE_TEST(Type) template Test::Test(ParamTraits<Type>::ParamType)

INSTANTIATE_TEST(int);
INSTANTIATE_TEST(long);
INSTANTIATE_TEST(std::string);
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[6]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 13:03
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX>Здравствуйте, remark, Вы писали:


R>>Вывести надо Type, а не ParamType. Хотя я тут не очень силён.

R>>Ну ладно, это не важно. Всё равно решения не получается.

CX>Хмм... Так тебе ParamTraits не нужен в конструкторе? Тогда может так подойдет:


Нет, он мне нужен, и именно в конструкторе.

Если быть более точным, то пример примерно такой:


// Структура задаёт тип параметра, который принимает конструктор
template<typename Type>
struct ParamTraits
{
    typedef Type1 ParamType1;
    typedef Type2 ParamType2;
    typedef Type3 ParamType3;
};


// Основной класс
class Test
{
public:
    // Шаблонный конструктор
    // принимает параметр типа, который определяется ParamTraits
    template<typename Type>
    Test(int, typename ParamTraits<Type>::ParamType1 param1, typename ParamTraits<Type>::ParamType2 param2, typename ParamTraits<Type>::ParamType3 param3);
};


И без TypeTraits тут сделать не получается.

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 13:05
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, swamper, Вы писали:


>>>> Здравствуйте, remark, Вы писали:


S>>А зачем нужно инстанцирование? Не совсем понятно, какой от этого будет толк.

S>>Тем не менее, вот пример кода, который инстанцирует шаблонную функцию:

S>>
S>>#define INSTANTIATE_TEST(Type)        \
S>>  template<typename T> struct dummy;  \
S>>  template<> struct dummy<Type> { Test test(ParamTraits<Type>::ParamType()); }
S>>



R>Интересный вариант. Не делать явное инстанциирование, а заставить компилятор инстанциировать.

R>Тут есть ограничение, что ParamTraits<Type>::ParamType должен иметь конструктор по-умолчанию, но в моём случае, это не страшно.

R>Хотя так всё равно не работает. Компилятор не инстанциирует шаблон.

R>Я написал что-то вроде этого:

R>
R>#define INSTANTIATE_TEST(Type)        \
R>  template<typename T> struct dummy;  \
R>  template<> struct dummy<Type> { dummy() {Test test(ParamTraits<Type>::ParamType());} };    \
R>  void func##Type ()    \
R>    {dummy<Type> dummy;};
R>


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

Тем более тут проблемы с типами типа std::string. Вот так записать не получчиться:

void func##Type ();

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: И опять синтаксис шаблонов...
От: Глеб Алексеев  
Дата: 03.10.05 13:09
Оценка:
Здравствуйте, remark, Вы писали:

R>Но, при компиляции:


R>
R>Test test(10);
R>


R>ругается:


R>error C2664: 'Test::Test(const Test &)' : cannot convert parameter 1 from 'int' to 'const Test &'


Заметь, ты получишь эту ошибку, даже если определение шаблона будет видимо. Т.е. к явному инстанцированию шаблона это отношенипя не имеет.
Дело в том, что в твоем коде агрумент шаблона из типа аргумента не выводится, как уже сказали раза 4. Следовательно, этот конструктор ты просто не сможешь вызвать, не добавив к нему dummy-аргументов.

А у VC все действительно оказалось еще более запущено, чем я думал, следующий легальный код компилить отказывается:
struct A {
  template <class T>
    A(typename traits<T>::type, T*dummy) {
    }
};
template A::A(traits<int>, int*);


Можно извратиться (вариации на тему уже предлагались):
template <class T>
void instantiate_A_ctor() {  
  A a( typename traits<T>::type(), (T*)0 );
}

template void instantiate_A_ctor<int>();
template void instantiate_A_ctor<bool>();


Но чего мы добились? Объекты A теперь приходится создавать так:
A a1(0, (int*)0);
A a1(false, (bool*)0);

Как уже сказано, это не имеет отношения к явному инстанцированию конструкторов, проблема вызвана невозможностью вывести тип аргумента шаблона — компилятор не знает, какой конструктор вызвать, его приходится тыкать носом, что неудобно (дать указателю dummy значение =0 по умолчанию мы не можем по этой же причине).

ИМХО, если ты все равно собираешься явно перечислять все типы, для которых данный конструктор может быть вызван (иначе зачем явное инстанцирование?), то почему не облегчить жизнь себе и другим, просто перегрузив конструкторы для всех нужных типов? А реализация этих конструкторов уже может использовать любые злые шаблоны, какие только душе угодны.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 13:15
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Здравствуйте, remark, Вы писали:


R>>Но, при компиляции:


R>>
R>>Test test(10);
R>>


R>>ругается:


R>>error C2664: 'Test::Test(const Test &)' : cannot convert parameter 1 from 'int' to 'const Test &'


ГА>Заметь, ты получишь эту ошибку, даже если определение шаблона будет видимо. Т.е. к явному инстанцированию шаблона это отношенипя не имеет.

ГА>Дело в том, что в твоем коде агрумент шаблона из типа аргумента не выводится, как уже сказали раза 4. Следовательно, этот конструктор ты просто не сможешь вызвать, не добавив к нему dummy-аргументов.

ГА>А у VC все действительно оказалось еще более запущено, чем я думал, следующий легальный код компилить отказывается:

ГА>
ГА>struct A {
ГА>  template <class T>
ГА>    A(typename traits<T>::type, T*dummy) {
ГА>    }
ГА>};
ГА>template A::A(traits<int>::type, int*); // Наверное так
ГА>



Я про это и говорю — вся загвоздка в typename traits<T>::type.


ГА>Можно извратиться (вариации на тему уже предлагались):

ГА>
ГА>template <class T>
ГА>void instantiate_A_ctor() {  
ГА>  A a( typename traits<T>::type(), (T*)0 );
ГА>}

ГА>template void instantiate_A_ctor<int>();
ГА>template void instantiate_A_ctor<bool>();
ГА>


ГА>Но чего мы добились? Объекты A теперь приходится создавать так:

ГА>
ГА>A a1(0, (int*)0);
ГА>A a1(false, (bool*)0);
ГА>

ГА>Как уже сказано, это не имеет отношения к явному инстанцированию конструкторов, проблема вызвана невозможностью вывести тип аргумента шаблона — компилятор не знает, какой конструктор вызвать, его приходится тыкать носом, что неудобно (дать указателю dummy значение =0 по умолчанию мы не можем по этой же причине).

ГА>ИМХО, если ты все равно собираешься явно перечислять все типы, для которых данный конструктор может быть вызван (иначе зачем явное инстанцирование?), то почему не облегчить жизнь себе и другим, просто перегрузив конструкторы для всех нужных типов? А реализация этих конструкторов уже может использовать любые злые шаблоны, какие только душе угодны.



Я хотел как раз от этого уйти
У меня по 6 конструкторов для 10 типов... Раньше было сделано с помощью макросов. Всё таки от макросов не уйти

Всё таки если без шаблонов, то во-первых, будут макросы, чего хотелось бы избежать (в данном случае ещё мешает дебажить), во-вторых, будет значительное дублирование кода — даже если в этих конструкторах будет по одной строчке, менять их все вместе геморойно.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 13:20
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Здравствуйте, remark, Вы писали:


R>>Но, при компиляции:


R>>
R>>Test test(10);
R>>


R>>ругается:


R>>error C2664: 'Test::Test(const Test &)' : cannot convert parameter 1 from 'int' to 'const Test &'


ГА>Заметь, ты получишь эту ошибку, даже если определение шаблона будет видимо. Т.е. к явному инстанцированию шаблона это отношенипя не имеет.

ГА>Дело в том, что в твоем коде агрумент шаблона из типа аргумента не выводится, как уже сказали раза 4. Следовательно, этот конструктор ты просто не сможешь вызвать, не добавив к нему dummy-аргументов.

Аааа... Вы всё имеете в виду, что он не выводиться при вызове конструктора, меня пока волнует почему ошибка в строчке, где я явно инстанциирую шаблон:

template Test::Test(ParamTraits<int>::ParamType);



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: И опять синтаксис шаблонов...
От: Глеб Алексеев  
Дата: 03.10.05 13:27
Оценка:
Здравствуйте, remark, Вы писали:

R>Аааа... Вы всё имеете в виду, что он не выводиться при вызове конструктора, меня пока волнует почему ошибка в строчке, где я явно инстанциирую шаблон:

Так это же вроде уже выяснили. Глюк VC, Комо замечательно компилит явное инстанцирование конструкторов независимо от выводимости аргументов шаблона. Остальное относилось к тому, что все обходные пути того не стоят, т.к. вызвать нужный конструктор все равно не получится, если аргументы шаблона не выводятся, даже на идеальном компиляторе.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 13:31
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Здравствуйте, remark, Вы писали:


R>>Аааа... Вы всё имеете в виду, что он не выводиться при вызове конструктора, меня пока волнует почему ошибка в строчке, где я явно инстанциирую шаблон:

ГА>Так это же вроде уже выяснили. Глюк VC, Комо замечательно компилит явное инстанцирование конструкторов независимо от выводимости аргументов шаблона. Остальное относилось к тому, что все обходные пути того не стоят, т.к. вызвать нужный конструктор все равно не получится, если аргументы шаблона не выводятся, даже на идеальном компиляторе.

Хорошо, понял.
А если изменить условия, т.ч. первый аргумент конструктора всегда int, второй — всегда Type (сам параметр шаблона), а второй через traits, т.е. так сказать сдвинуть точку отсчёта в первый шаблонный параметр.

    template<typename Type>
    Test(int, Type type, typename ParamTraits<Type>::ParamType param);


Так получиться?

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 03.10.05 13:40
Оценка:
Здравствуйте, remark, Вы писали:

R>Нет, он мне нужен, и именно в конструкторе.


Выходит, что тебе все-таки нужен ParamTraits, а вывести его из зависимого имени ParamType не получится. Поэтому его надо указывать явно.

R>Если быть более точным, то пример примерно такой:


R>
R>// Структура задаёт тип параметра, который принимает конструктор
R>template<typename Type>
R>struct ParamTraits
R>{
R>    typedef Type1 ParamType1;
R>    typedef Type2 ParamType2;
R>    typedef Type3 ParamType3;
R>};


R>// Основной класс
R>class Test
R>{
R>public:
R>    // Шаблонный конструктор
R>    // принимает параметр типа, который определяется ParamTraits
R>    template<typename Type>
R>    Test(int, typename ParamTraits<Type>::ParamType1 param1, typename ParamTraits<Type>::ParamType2 param2, typename ParamTraits<Type>::ParamType3 param3);
R>};
R>


R>И без TypeTraits тут сделать не получается.


Я не совсем понимаю. Зачем здесь ParamTraits? Для автоматического выведения типа? Так это в любом случае не получится. Или еще для чего?
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[8]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 13:48
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX>Здравствуйте, remark, Вы писали:


R>>Нет, он мне нужен, и именно в конструкторе.


CX>Выходит, что тебе все-таки нужен ParamTraits, а вывести его из зависимого имени ParamType не получится. Поэтому его надо указывать явно.


R>>Если быть более точным, то пример примерно такой:


R>>
R>>// Структура задаёт тип параметра, который принимает конструктор
R>>template<typename Type>
R>>struct ParamTraits
R>>{
R>>    typedef Type1 ParamType1;
R>>    typedef Type2 ParamType2;
R>>    typedef Type3 ParamType3;
R>>};


R>>// Основной класс
R>>class Test
R>>{
R>>public:
R>>    // Шаблонный конструктор
R>>    // принимает параметр типа, который определяется ParamTraits
R>>    template<typename Type>
R>>    Test(int, typename ParamTraits<Type>::ParamType1 param1, typename ParamTraits<Type>::ParamType2 param2, typename ParamTraits<Type>::ParamType3 param3);
R>>};
R>>


R>>И без TypeTraits тут сделать не получается.


CX>Я не совсем понимаю. Зачем здесь ParamTraits? Для автоматического выведения типа? Так это в любом случае не получится. Или еще для чего?



ParamTraits используется собственно по прямому назначению нужны разные наборы типов для параметров конструктора. А именно, например:

Для int:

Test::Test(int& value, int defaultValue);


Для std::string:

Test::Test(std::string& value, const std::stirng& defaultValue);


Для char*:

Test::Test(char* buf, const std::stirng& defaultValue);



В принципе можно немного переформулировать постановку задачи:
здесь
Автор: remark
Дата: 03.10.05

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 03.10.05 13:50
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Так это же вроде уже выяснили. Глюк VC, Комо замечательно компилит явное инстанцирование конструкторов независимо от выводимости аргументов шаблона.


Не совсем так. В случае, если типы невыводимы из аргументов, Комо выдает ошибку. Первоначальный пример он не компилирует. Но если изменить шаблон INSTANTIATE_TEST, указав явно тип, с которым нужно инстанцировать, все пройдет на ура. К сожалению, VC 7.1 содержит баг, заключающийся в том, что явное инстанцирование шаблонов конструкторов он не производит при явном указании типа.
#define INSTANTIATE_TEST(Type) template Test::Test(ParamTraits<Type>::ParamType) // Так неверно
#define INSTANTIATE_TEST(Type) template Test::Test<Type>(ParamTraits<Type>::ParamType) // А вот так все ОК, но не для VC 7.1
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[7]: И опять синтаксис шаблонов...
От: Глеб Алексеев  
Дата: 03.10.05 13:51
Оценка: 3 (1) +1
Здравствуйте, remark, Вы писали:

R>Хорошо, понял.

R>А если изменить условия, т.ч. первый аргумент конструктора всегда int, второй — всегда Type (сам параметр шаблона), а второй через traits, т.е. так сказать сдвинуть точку отсчёта в первый шаблонный параметр.

R>
R>    template<typename Type>
R>    Test(int, Type type, typename ParamTraits<Type>::ParamType param);
R>

R>Так получиться?

Получится, но опять через ..гм, Амстердам, т.к. VC и в этом случае будет глючить при попытке явно инстанцировать, нужно идти в обход (варианты уже предлагались).
Сделай проще:
#include <string>

template <class T>
struct traits {
  typedef T type; 
};

template <>
struct traits<std::string> {
  typedef const std::string& type; 
};


struct A {
  template <class T, class P>
    A(T t, P p /* раньше вместо P был typename traits<T>::type */) {
    }
};


template A::A(std::string, traits<std::string>::type);
template A::A(int, traits<int>::type);

Не страшно, что типы T и P в объявлении конструктора никак не связаны, т.к. он инстанцируется явно и допустимые типы все равно под твоим контролем (правда, диагностика ошибок сдвинется на фазу компоновки).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: И опять синтаксис шаблонов...
От: Глеб Алексеев  
Дата: 03.10.05 13:53
Оценка:
Здравствуйте, CrystaX, Вы писали:

ГА>>Так это же вроде уже выяснили. Глюк VC, Комо замечательно компилит явное инстанцирование конструкторов независимо от выводимости аргументов шаблона.

CX>Не совсем так. В случае, если типы невыводимы из аргументов, Комо выдает ошибку. Первоначальный пример он не компилирует. Но если изменить шаблон INSTANTIATE_TEST, указав явно тип, с которым нужно инстанцировать, все пройдет на ура. К сожалению, VC 7.1 содержит баг, заключающийся в том, что явное инстанцирование шаблонов конструкторов он не производит при явном указании типа.
CX>
CX>#define INSTANTIATE_TEST(Type) template Test::Test(ParamTraits<Type>::ParamType) // Так неверно
CX>#define INSTANTIATE_TEST(Type) template Test::Test<Type>(ParamTraits<Type>::ParamType) // А вот так все ОК, но не для VC 7.1
CX>

Я имел в виду, что Комо справляется со вторым случаем.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 03.10.05 13:57
Оценка:
Здравствуйте, remark, Вы писали:

R>В принципе можно немного переформулировать постановку задачи:

R>здесь
Автор: remark
Дата: 03.10.05


Все равно не понимаю, какие из этого выгоды. У тебя что, во всех случаях одно и то же тело конструктора? Или все-таки разное? И еще — каким образом в данной ситуации может помочь явное инстанцирование?
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[10]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 14:06
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX>Здравствуйте, remark, Вы писали:


R>>В принципе можно немного переформулировать постановку задачи:

R>>здесь
Автор: remark
Дата: 03.10.05


CX>Все равно не понимаю, какие из этого выгоды. У тебя что, во всех случаях одно и то же тело конструктора?

А что такого? Нельзя?
Да, тело одинаковое и шаблонное, т.е. в нём тоже вызываются шаблонные функции.

CX>Или все-таки разное? И еще — каким образом в данной ситуации может помочь явное инстанцирование?


Явное инстанциирование нужно, что бы не было модели включения, что бы компилировать в каждом файле кучу шаблонов, + типы для которых надо инстанциировать известны и фиксированы + это всё будет в библиотеке .lib

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 14:08
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Здравствуйте, remark, Вы писали:


R>>Хорошо, понял.

R>>А если изменить условия, т.ч. первый аргумент конструктора всегда int, второй — всегда Type (сам параметр шаблона), а второй через traits, т.е. так сказать сдвинуть точку отсчёта в первый шаблонный параметр.

R>>
R>>    template<typename Type>
R>>    Test(int, Type type, typename ParamTraits<Type>::ParamType param);
R>>

R>>Так получиться?

ГА>Получится, но опять через ..гм, Амстердам, т.к. VC и в этом случае будет глючить при попытке явно инстанцировать, нужно идти в обход (варианты уже предлагались).

ГА>Сделай проще:

...

ГА>Не страшно, что типы T и P в объявлении конструктора никак не связаны, т.к. он инстанцируется явно и допустимые типы все равно под твоим контролем (правда, диагностика ошибок сдвинется на фазу компоновки).



Ясно. Спасибо. Вариант хороший. Значит всё-таки это msvc глючит...
Правда речь идёт о классе из библиотеки. Пока это выглядело как:

Test::Test(int& value, int defaultValue);
Test::Test(std::string& value, const std::stirng& defaultValue);
Test::Test(char* buf, const std::stirng& defaultValue);


Было всё достаточно понятно, а так :

 template <class T, class P>
A(T t, P p);





Ну ладно придётся документировать.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 03.10.05 14:13
Оценка:
Здравствуйте, remark, Вы писали:

R>А что такого? Нельзя?

R>Да, тело одинаковое и шаблонное, т.е. в нём тоже вызываются шаблонные функции.

Можно. Но у меня сложилось впечатление, что тело разное.

CX>>Или все-таки разное? И еще — каким образом в данной ситуации может помочь явное инстанцирование?


R>Явное инстанциирование нужно, что бы не было модели включения, что бы компилировать в каждом файле кучу шаблонов, + типы для которых надо инстанциировать известны и фиксированы + это всё будет в библиотеке .lib


Ну это-то понятно. Просто показалось, что ты таким образом пытаешься наложить определенные ограничения compile- и/или link-time.

... << RSDN@Home 1.1.4 stable rev. 510>>
Re[9]: И опять синтаксис шаблонов...
От: Глеб Алексеев  
Дата: 03.10.05 14:36
Оценка: 1 (1)
Здравствуйте, remark, Вы писали:


R>Ясно. Спасибо. Вариант хороший. Значит всё-таки это msvc глючит...

R>Правда речь идёт о классе из библиотеки. Пока это выглядело как:
R>
R>Test::Test(int& value, int defaultValue);
R>Test::Test(std::string& value, const std::stirng& defaultValue);
R>Test::Test(char* buf, const std::stirng& defaultValue);
R>

R>Было всё достаточно понятно, а так :
R>
R> template <class T, class P>
R>A(T t, P p);
R>

Вот здесь ты противоречишь сам себе. Недавно ты говорил, что перегрузок конструкторов для всех типов параметров нет, точнее, ты хочешь от них избавиться.
Кроме того, для среднего пользователя
template <class T>
A(T& value, typename traits<T>::type dflt);

будет выглядеть не понятнее, чем
template <class T, class P>
A(T& value , P default);


В любом случае, сам шаблонный конструктор вида template <class T, class P> A(...) можно перенести в закрытый базовый класс, а в интерфейсной части библиотеки использовать либо множество перегруженных конструкторов, либо вариант с traits. Как-нибудь так:
//lib.hpp
namespace detail {
struct a_base {
  template <class T, class P>
    a_base(T& , P);
};
}
struct a : private detail::a_base {
  template <class T>
    a(T& val, typename traits<T>::type dflt) : a_base(val, dflt) {
    }
};

//lib.cpp
namespace detail {
template <class T, class P>
a_base::a_base(T& , P) {
// implementation
}
template a_base::a_base(string, traits<string>::type);
template a_base::a_base(int, traits<int>::type);
// ...
}


R>Ну ладно придётся документировать.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[10]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 03.10.05 14:46
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Вот здесь ты противоречишь сам себе. Недавно ты говорил, что перегрузок конструкторов для всех типов параметров нет, точнее, ты хочешь от них избавиться.


Да так и есть. Не понял.

ГА>Кроме того, для среднего пользователя

ГА>
ГА>template <class T>
ГА>A(T& value, typename traits<T>::type dflt);
ГА>

ГА>будет выглядеть не понятнее, чем
ГА>
ГА>template <class T, class P>
ГА>A(T& value , P default);
ГА>


Согласен. Надо просто их переназвать — не T и P, а типа ValueType и ReferenceType.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: И опять синтаксис шаблонов...
От: Глеб Алексеев  
Дата: 03.10.05 14:53
Оценка:
Здравствуйте, remark, Вы писали:

ГА>>Вот здесь ты противоречишь сам себе. Недавно ты говорил, что перегрузок конструкторов для всех типов параметров нет, точнее, ты хочешь от них избавиться.

R>Да так и есть. Не понял.

Разве ты не говорил:
R>Правда речь идёт о классе из библиотеки. Пока это выглядело как:
R>Test::Test(int& value, int defaultValue);
R>Test::Test(std::string& value, const std::stirng& defaultValue);
R>Test::Test(char* buf, const std::stirng& defaultValue);

R>Было всё достаточно понятно,
?

R>Согласен. Надо просто их переназвать — не T и P, а типа ValueType и ReferenceType.

Тогда уж не ReferenceType, а ArgumentType.
А еще лучше сделать так, как я предложил (с базовым классом), тогда еще и диагностика на стадии компиляции будет.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[12]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 04.10.05 08:07
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Здравствуйте, remark, Вы писали:


ГА>>>Вот здесь ты противоречишь сам себе. Недавно ты говорил, что перегрузок конструкторов для всех типов параметров нет, точнее, ты хочешь от них избавиться.

R>>Да так и есть. Не понял.

ГА>Разве ты не говорил:

R>>Правда речь идёт о классе из библиотеки. Пока это выглядело как:
ГА>
R>>Test::Test(int& value, int defaultValue);
R>>Test::Test(std::string& value, const std::stirng& defaultValue);
R>>Test::Test(char* buf, const std::stirng& defaultValue);
ГА>

R>>Было всё достаточно понятно,
ГА>?

Ну, да. Я хочу, что бы стало:

Test::Test(ParamType1 value, ParamType2 defaultValue);



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 04.10.05 08:11
Оценка: :)
Здравствуйте, Глеб Алексеев, Вы писали:


ГА>В любом случае, сам шаблонный конструктор вида template <class T, class P> A(...) можно перенести в закрытый базовый класс, а в интерфейсной части библиотеки использовать либо множество перегруженных конструкторов, либо вариант с traits. Как-нибудь так:

ГА>
ГА>//lib.hpp
ГА>namespace detail {
ГА>struct a_base {
ГА>  template <class T, class P>
ГА>    a_base(T& , P);
ГА>};
ГА>}
ГА>struct a : private detail::a_base {
ГА>  template <class T>
ГА>    a(T& val, typename traits<T>::type dflt) : a_base(val, dflt) {
ГА>    }
ГА>};

ГА>//lib.cpp
ГА>namespace detail {
ГА>template <class T, class P>
ГА>a_base::a_base(T& , P) {
ГА>// implementation
ГА>}
ГА>template a_base::a_base(string, traits<string>::type);
ГА>template a_base::a_base(int, traits<int>::type);
ГА>// ...
ГА>}
ГА>



А вот это попробуйте



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 04.10.05 11:37
Оценка: 1 (1) +1
Здравствуйте, remark, Вы писали:

Собственно, по сути это то же самое, что я предложил здесь
Автор: CrystaX
Дата: 03.10.05
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[10]: И опять синтаксис шаблонов...
От: remark Россия http://www.1024cores.net/
Дата: 04.10.05 11:50
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX>Здравствуйте, remark, Вы писали:


CX>Собственно, по сути это то же самое, что я предложил здесь
Автор: CrystaX
Дата: 03.10.05


Ну вообще, там
Автор: CrystaX
Дата: 03.10.05
идея тоже интересная.
Я всё-таки решил в итоге делать немного подругому:
Т.к. это один из основных классов, который торчит из библиотеки, я всё-таки вручную (через макросы) записал все возможные конструкторы. А в реализации (которая тоже сделана с помощью макросов) сразу же (в одну строчку) перенаправляю логику во внутреннюю шаблонную часть.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: И опять синтаксис шаблонов...
От: CrystaX Россия https://crystax.me/
Дата: 04.10.05 11:54
Оценка:
Здравствуйте, remark, Вы писали:

R>Я всё-таки решил в итоге делать немного подругому:

R>Т.к. это один из основных классов, который торчит из библиотеки, я всё-таки вручную (через макросы) записал все возможные конструкторы. А в реализации (которая тоже сделана с помощью макросов) сразу же (в одну строчку) перенаправляю логику во внутреннюю шаблонную часть.

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

R>

А вот с этим согласен.
... << RSDN@Home 1.1.4 stable rev. 510>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.