Specialize function template with decltype trailing return type

Christian Hackl

In C++11, how can I specialise a function template which is declared with a "complicated" trailing return type using decltype? The following works in GCC but produces "error C2912: explicit specialisation 'int f(void)' i s not a specialisation of a function template" in VC2013:

#include <iostream>

int myint() { return 1; }

template<class T>
auto f() -> decltype(myint()) // this seems to cause problems
{
    std::cout << "general\n";
    return 1;
}

template <>
auto f<double>() -> decltype(myint())
{
    std::cout << "special\n";
    return 2;
}

int main()
{
    f<int>();
    f<double>(); // compiler error in VC, but not in GCC
}

I say "complicated" in lack of a technically precise word because I'm not sure what makes the difference. For example, the following decltype, using a built-in operation not depending on any function result type, works fine with template specialisation:

auto f() -> decltype(1 + 1)

So, my questions (all related to each other):

  1. Is my code correct C++11?
  2. Is this a VC bug?
  3. How could I ever specialise std::begin and std::end (and thus provide range-based for loops) for an unchangeable legacy container class if this kind of specialization does not work?
Ali

Is my code correct C++11?

Looks correct to me. Also, compiles cleanly both with gcc and clang with -Wall -Wextra.

Is this a VC bug?

Most likely. VC is infamous in this respect, see for example What exactly is "broken" with Microsoft Visual C++'s two-phase template instantiation? or google msvc two-phase lookup.

How could I ever specialise std::begin and std::end (and thus provide range-based for loops) for an unchangeable legacy container class if this kind of specialization does not work?

For the code you provided, a workaround would be to use a typedef:

#include <iostream>

int myint() { return 1; }

typedef decltype(myint()) return_type;

template<class T>
return_type f()
{
    std::cout << "general\n";
    return 1;
}

template <>
return_type f<double>()
{
    std::cout << "special\n";
    return 2;
}

int main()
{
    f<int>();
    f<double>();
}

All three mainstream compilers (gcc, clang, vs) seem to be happy with this code.


UPDATE:

How could I ever specialise std::begin and std::end (and thus provide range-based for loops) for an unchangeable legacy container class if this kind of specialization does not work?
[And from the comments:] I thought specialising std::begin and std::end was always the best approach.

After giving it some thought, specializing std::begin() and std::end() would be my last resort. My first attempt would be to provide member begin() and end() functions; unfortunately, it is not an option for you because you cannot modify the corresponding code. Then, my second attempt would be to provide free functions in my own namespace:

#include <iostream>
#include <initializer_list>
#include <vector>

namespace my_namespace {

template <typename T> class my_container;
template <typename T> T* begin(my_container<T>& c);
template <typename T> T* end(my_container<T>& c);

template <typename T>
class my_container {

  public:

    explicit my_container(std::initializer_list<T> list) : v(list) { }

    friend T* begin<>(my_container& c);
    friend T* end<>(my_container& c);

  private:

    std::vector<T> v;
};

template <typename T>
T* begin(my_container<T>& c) {

  return c.v.data();
}

template <typename T>
T* end(my_container<T>& c) {

  return c.v.data()+c.v.size();
}

}

int main() {

  my_namespace::my_container<int> c{1, 2, 3};

  for (int i : c)
    std::cout << i << '\n';
}

This approach must work if you were able to specialize std::begin() and std::end() for the container. It also works if you do it in the global namespace (that is, you simply omit the namespace my_namespace { and closing }) but I prefer to put my implementation into my own namespace.

See also

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Specialize function template with decltype trailing return type

From Dev

Specialize auto trailing return type

From Dev

decltype for the return type of recursive variadic function template

From Dev

In C++ 11, how do I specialize a function template that takes a function object based on return type?

From Dev

Is there a way to specialize a function template by an array type?

From Dev

C++11 trailing return member function using decltype and constness

From Java

Trailing return type in non-template functions

From Dev

Trailing Return Type on operator* In Template Class

From Dev

decltype with two parameters, = decltype(a,b), for function return type

From Dev

decltype with two parameters, = decltype(a,b), for function return type

From Dev

Specialize template function for string iterator using type traits

From Dev

Using a function pointer with a trailing return type

From Dev

Failed to specialize function template in threads

From Dev

How to specialize template member function?

From Dev

Failed to specialize function template in threads

From Dev

Specialize function template for set of types

From Dev

C++ - specialize function template on a templated class with a non type template parameter

From Dev

Template member functions with trailing return type, giving errors even if unused

From Dev

Template member functions with trailing return type, giving errors even if unused

From Dev

return type of decltype(*this)

From Dev

How to specialize template function with template types

From Dev

Specialize template with function pointer, that depends on template parameter

From Dev

let function return template type

From Dev

Order of declaration matters when using decltype for member function return type

From Dev

C++: Deriving a function return type using decltype

From Dev

template argument deduction of return type in function template

From Dev

template argument deduction of return type in function template

From Dev

Trailing return type and rvalues

From Dev

Trailing return type array

Related Related

  1. 1

    Specialize function template with decltype trailing return type

  2. 2

    Specialize auto trailing return type

  3. 3

    decltype for the return type of recursive variadic function template

  4. 4

    In C++ 11, how do I specialize a function template that takes a function object based on return type?

  5. 5

    Is there a way to specialize a function template by an array type?

  6. 6

    C++11 trailing return member function using decltype and constness

  7. 7

    Trailing return type in non-template functions

  8. 8

    Trailing Return Type on operator* In Template Class

  9. 9

    decltype with two parameters, = decltype(a,b), for function return type

  10. 10

    decltype with two parameters, = decltype(a,b), for function return type

  11. 11

    Specialize template function for string iterator using type traits

  12. 12

    Using a function pointer with a trailing return type

  13. 13

    Failed to specialize function template in threads

  14. 14

    How to specialize template member function?

  15. 15

    Failed to specialize function template in threads

  16. 16

    Specialize function template for set of types

  17. 17

    C++ - specialize function template on a templated class with a non type template parameter

  18. 18

    Template member functions with trailing return type, giving errors even if unused

  19. 19

    Template member functions with trailing return type, giving errors even if unused

  20. 20

    return type of decltype(*this)

  21. 21

    How to specialize template function with template types

  22. 22

    Specialize template with function pointer, that depends on template parameter

  23. 23

    let function return template type

  24. 24

    Order of declaration matters when using decltype for member function return type

  25. 25

    C++: Deriving a function return type using decltype

  26. 26

    template argument deduction of return type in function template

  27. 27

    template argument deduction of return type in function template

  28. 28

    Trailing return type and rvalues

  29. 29

    Trailing return type array

HotTag

Archive