Шаблонный конструктор не может выполнить преобразование - PullRequest
1 голос
/ 18 июня 2019

Вот отдельный пример использования того, чего я пытаюсь достичь

//Bar.hpp

#ifndef BAR_HPP
#define BAR_HPP

constexpr bool areNamesEqual(const char* name1,const char* name2)
{
    return ((*name1 == *name2) && (*name1 == '\0' ||  areNamesEqual(name1 + 1,name2 + 1)));
}
#endif

Тогда у меня есть класс, который использует эту утилиту сравнения следующим образом

// Foo.hpp

#ifndef FOO_HPP
#define FOO_HPP

#include "Bar.hpp"

class Foo 
{
    public:
    template<typename T_0>
    Foo(const T_0 & var_0)
    {   
        static_assert(areNamesEqual(T_0::formatter_name,"Hole"),"Incorrect hole type supplied!");
    }   
};

#endif 

Наконец, у меня есть другой класс, который фактически предоставляет аргумент для сравнения следующим образом

// Hole.hpp

#ifndef HOLE_HPP
#define HOLE_HPP

class Hole {
    public:

        Hole(double dx) : d(dx) {}

        static constexpr const char* formatter_name = "Hole";
    private:
        double d;
  };
#endif

В моем main.cpp, когда я вызываю это, как показано ниже

//main.cpp
#include "Foo.hpp"
#include "Hole.hpp"

int main()
{
    Foo f(43);
    return 0;
}

g ++ (6.3) с --std = c ++ 14 выдает мне следующую ошибку

In file included from main.cpp:1:0:
Foo.hpp: In instantiation of ‘Foo::Foo(const T_0&) [with T_0 = int]’:
main.cpp:6:13:   required from here
Foo.hpp:12:36: error: ‘formatter_name’ is not a member of ‘int’
         static_assert(areNamesEqual(T_0::formatter_name,"Hole"),"Incorrect hole type supplied!");

Почему компилятор не может неявно преобразовать тип double в класс Hole? Я не уверен, поможет ли мне здесь оператор преобразования класса Hole.

: UPDATE: Обновлен фрагмент кода для отображения ошибки для int literal.

1 Ответ

2 голосов
/ 18 июня 2019

Давайте проанализируем ошибку компилятора:

Foo.hpp: в экземпляре ‘Foo :: Foo (const T_0 &) [with T_0 = int]’:

Означает T_0 выводится для типа int (примечание: вы уверены, что не выдает ошибку, когда пытались использовать 43 литерал вместо 43.0?)

Итак, тип T_0 зафиксирован здесь. Тогда:

Foo.hpp: 12: 36: ошибка: «имя_форматера» не является членом «int».

Что верно: примитивный тип int вообще не имеет членов, поэтому он не имеет, в частности, formatter_name члена.

Это объясняет ошибку, которая предписана стандартом C ++.


Теперь вы упоминаете об ожидаемом преобразовании, это из-за конструктора non - explicit для Hole, принимающего double?

Если это так, это преобразование неявно произойдет, только если вы дадите двойное значение «контексту», ожидающему экземпляр Hole.

Например, если вы изменили инициализацию Foo на Foo f<Hole>(43.0); или Foo f(Hole{43.0});

Это абсолютно не так в вашем примере: вы даете двойной конструктор Foo, который основан на типе аргумента, и вы сами не используете тип шаблона. Таким образом, вычитается тип шаблона функции, и он точно соответствует типу аргумента. Кроме того, реализация любого оператора преобразования не изменит этого факта.

...