[cfe-dev] template instantiation, typedef used as template argument and dependent type for data members.

Philippe Canal pcanal at fnal.gov
Mon Jun 25 09:52:40 PDT 2012


Hi,

In the context of ROOT (<http://root.cern.ch>), it's automated I/O of C++
objects, and of the cling Interpreter (<http://root.cern.ch/drupal/content/cling>,
we are strongly hindered by the fact that template instantiations that have
a typedef as template parameter 'forget' about it in the AST (at least
as far as the data members and member functions of the template instance
are concerned).

In ROOT I/O we use two typedefs (Float16_t and Double32_t) to indicates
that even-though the data member should have full precision while in
memory and while involved in computation, when being stored they
should be stored with lower precision.

When using for example:

    // Start of file templateAndTypedef.C
    //
    // This typedef indicates that the user would
    // like to store the data on disk with only
    // 32 bits of precision.
    typedef double Double32_t;
    // This typedef indicates that the user would
    // like to store the data on disk with only
    // 16 bits of precision.
    typedef float Float16_t;

    template <typename T>
    class Data
    {
    private:
       Float16_t m_Common;
       T             m_UserDetermined;
    };

    class Event {
    private:
       Data<double>     m_FullPrecision;
       Data<Double32_t> m_LimitedRange;
    };
    // end of file templateAndTypedef.C

we get:

    clang++ -cc1 -ast-dump templateAndTypedef.C
    ....
    typedef double Double32_t;
    typedef float Float16_t;
    template <typename T = double> class Data {
        class Data;
    private:
        Float16_t m_Common;
        double m_UserDetermined;
    }
    template <typename T> class Data {
        class Data;
    private:
       Float16_t m_Common;
       T m_UserDetermined;
    };
    class Event {
        class Event;
    private:
        Data<double> m_FullPrecision;
        Data<Double32_t> m_LimitedRange;
    };

Which in particular means that when we follow the AST nodes
from the class Event down to inside the type of m_LimitedRange,
we are brought to 'just' the content of the generic Data<double>
instantiation.   Where in particular we have lost the
information that 'm_UserDetermined' was 'meant' by the user
to be a Double32_t.   In contrast, we still have the information
that the developer meant that m_Common should be a Float16_t.


Having access to the 'intended' type description from a template
instantiation is here fundamental for the ROOT I/O mechanism
to work properly (the semantic and on file format of 'double'
and 'Double32_t' being very different).

Using an alternative to the typedef for this purpose has its
own set of problems as we also need things like
std::vector<Double32_t> and std::vector<double> to be
interchangeable (for example as far as parameter passing
is concerned).


In addition to our use case, having access to this type
of information could be useful for a document generator
or to clarify/simplify some error messages.   For example:

    // start of stringError.C
    #include <string>
    #include <vector>
    void test ()
    {
       std::vector<std::string> vec;
       vec.push_back("abc");
       vec.push_back(1.3);
    }
    // end of stringError.C

when compiled with clang, the output currently contains the error message:

stringError.C:8:18: error: reference to type 'const value_type' (aka 'const std::basic_string<char>') could not bind to an rvalue of 
type 'double'
    vec.push_back(1);
                  ^

which would be even nicer, if reading:


stringError.C:8:18: error: reference to type 'const value_type' (aka 'const std::string') could not bind to an rvalue of type 'int'
    vec.push_back(1);
                  ^

where 'std::basic_string<char>' has been replaced by 'std::string'.

In first approximation, one plausible step could be to generate a distinct
template instantiations for each of the cases with distinct typedef
as a template argument and a template instantiation for the case
without typedef as a template argument (i.e. the primary template
instantiation).   And then make sure that for the rest of the semantic
analysis vector<Double32_t> and vector<double> are
treated as equivalent/interchangeable/aliases.


Any ideas/thoughts on if and how being able to access the intended
type of a template instantiation's members whose type depends on the
template parameter(s) could be supported in any way?

Thanks,
Philippe.















-------------- next part --------------
A non-text attachment was scrubbed...
Name: templateAndTypedef.C
Type: text/x-c++
Size: 487 bytes
Desc: templateAndTypedef.C
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120625/c862204d/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: stringError.C
Type: text/x-c++
Size: 136 bytes
Desc: stringError.C
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120625/c862204d/attachment-0001.bin>


More information about the cfe-dev mailing list