Skip to main content
Became Hot Network Question
deleted 5 characters in body
Source Link
wohlstad
  • 37.2k
  • 19
  • 80
  • 117
#include <iostream>
#include <type_traits>
#include <vector>
#include <string>

// ------------------------------------------------------------
// Tag types: int_tag and float_tag
// ------------------------------------------------------------
struct int_tag {};
struct float_tag {};

// ------------------------------------------------------------
// 2) Primary template: process_data (generic version)
// ------------------------------------------------------------
// template <typename Tag, typename T, typename U>
// void process_data(Tag tag, const T& a, const U& b) {
//     std::cout << "<unsupported type>" << "\n";
// }

template <typename Tag, typename A, typename B, typename Enable = void>
void process_data(Tag tag, const A& a, const B& b) {
    std::cout << "<unsupported type>" << "\n";
}

// ------------------------------------------------------------
// 3) Tag-dispatched function for int_tag (sum two integral numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<U>, void>
// process_data(int_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a + b) << "\n";  // Sum for integral types
// }

template <typename A, typename B, std::enable_if_t<std::is_integral_v<A> && std::is_integral_v<B>>>
void process_data(int_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a + b) << "\n";
}

// ------------------------------------------------------------
// 4) Tag-dispatched function for float_tag (multiply two floating-point numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_floating_point_v<T> && std::is_floating_point_v<U>, void>
// process_data(float_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a * b) << "\n";  // Product for floating-point types
// }

template <typename A, typename B, std::enable_if_t<std::is_floating_point_v<A> && std::is_floating_point_v<B>>>
void process_data(float_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a * b) << "\n";
}

// ------------------------------------------------------------
// TESTS (do NOT change)
// ------------------------------------------------------------

int main() {
    bool all_ok = true;

    // Test: process_data for int_tag
    std::cout << "[process_data for int_tag]\n";
    std::cout << "int: ";
    process_data(int_tag{}, 10, 20);  // Should print: Result: 30
    std::cout << "float: ";
    process_data(float_tag{}, 3.14f, 2.0f);  // Should print: Result: 6.28
    std::cout << "string: ";
    process_data(int_tag{}, "Hello", "World");  // Should print: <unsupported type>



    return 0;
}
#include <iostream>
#include <type_traits>
#include <vector>
#include <string>

// ------------------------------------------------------------
// Tag types: int_tag and float_tag
// ------------------------------------------------------------
struct int_tag {};
struct float_tag {};

// ------------------------------------------------------------
// 2) Primary template: process_data (generic version)
// ------------------------------------------------------------
// template <typename Tag, typename T, typename U>
// void process_data(Tag tag, const T& a, const U& b) {
//     std::cout << "<unsupported type>" << "\n";
// }

template <typename Tag, typename A, typename B, typename Enable = void>
void process_data(Tag tag, const A& a, const B& b) {
    std::cout << "<unsupported type>" << "\n";
}

// ------------------------------------------------------------
// 3) Tag-dispatched function for int_tag (sum two integral numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<U>, void>
// process_data(int_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a + b) << "\n";  // Sum for integral types
// }

template <typename A, typename B, std::enable_if_t<std::is_integral_v<A> && std::is_integral_v<B>>>
void process_data(int_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a + b) << "\n";
}

// ------------------------------------------------------------
// 4) Tag-dispatched function for float_tag (multiply two floating-point numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_floating_point_v<T> && std::is_floating_point_v<U>, void>
// process_data(float_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a * b) << "\n";  // Product for floating-point types
// }

template <typename A, typename B, std::enable_if_t<std::is_floating_point_v<A> && std::is_floating_point_v<B>>>
void process_data(float_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a * b) << "\n";
}

// ------------------------------------------------------------
// TESTS (do NOT change)
// ------------------------------------------------------------

int main() {
    bool all_ok = true;

    // Test: process_data for int_tag
    std::cout << "[process_data for int_tag]\n";
    std::cout << "int: ";
    process_data(int_tag{}, 10, 20);  // Should print: Result: 30
    std::cout << "float: ";
    process_data(float_tag{}, 3.14f, 2.0f);  // Should print: Result: 6.28
    std::cout << "string: ";
    process_data(int_tag{}, "Hello", "World");  // Should print: <unsupported type>

    return 0;
}
#include <iostream>
#include <type_traits>
#include <vector>
#include <string>

// ------------------------------------------------------------
// Tag types: int_tag and float_tag
// ------------------------------------------------------------
struct int_tag {};
struct float_tag {};

// ------------------------------------------------------------
// 2) Primary template: process_data (generic version)
// ------------------------------------------------------------
// template <typename Tag, typename T, typename U>
// void process_data(Tag tag, const T& a, const U& b) {
//     std::cout << "<unsupported type>" << "\n";
// }

template <typename Tag, typename A, typename B, typename Enable = void>
void process_data(Tag tag, const A& a, const B& b) {
    std::cout << "<unsupported type>" << "\n";
}

// ------------------------------------------------------------
// 3) Tag-dispatched function for int_tag (sum two integral numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<U>, void>
// process_data(int_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a + b) << "\n";  // Sum for integral types
// }

template <typename A, typename B, std::enable_if_t<std::is_integral_v<A> && std::is_integral_v<B>>>
void process_data(int_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a + b) << "\n";
}

// ------------------------------------------------------------
// 4) Tag-dispatched function for float_tag (multiply two floating-point numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_floating_point_v<T> && std::is_floating_point_v<U>, void>
// process_data(float_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a * b) << "\n";  // Product for floating-point types
// }

template <typename A, typename B, std::enable_if_t<std::is_floating_point_v<A> && std::is_floating_point_v<B>>>
void process_data(float_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a * b) << "\n";
}

// ------------------------------------------------------------
// TESTS (do NOT change)
// ------------------------------------------------------------

int main() {
    bool all_ok = true;

    // Test: process_data for int_tag
    std::cout << "[process_data for int_tag]\n";
    std::cout << "int: ";
    process_data(int_tag{}, 10, 20);  // Should print: Result: 30
    std::cout << "float: ";
    process_data(float_tag{}, 3.14f, 2.0f);  // Should print: Result: 6.28
    std::cout << "string: ";
    process_data(int_tag{}, "Hello", "World");  // Should print: <unsupported type>



    return 0;
}
#include <iostream>
#include <type_traits>
#include <vector>
#include <string>

// ------------------------------------------------------------
// Tag types: int_tag and float_tag
// ------------------------------------------------------------
struct int_tag {};
struct float_tag {};

// ------------------------------------------------------------
// 2) Primary template: process_data (generic version)
// ------------------------------------------------------------
// template <typename Tag, typename T, typename U>
// void process_data(Tag tag, const T& a, const U& b) {
//     std::cout << "<unsupported type>" << "\n";
// }

template <typename Tag, typename A, typename B, typename Enable = void>
void process_data(Tag tag, const A& a, const B& b) {
    std::cout << "<unsupported type>" << "\n";
}

// ------------------------------------------------------------
// 3) Tag-dispatched function for int_tag (sum two integral numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<U>, void>
// process_data(int_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a + b) << "\n";  // Sum for integral types
// }

template <typename A, typename B, std::enable_if_t<std::is_integral_v<A> && std::is_integral_v<B>>>
void process_data(int_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a + b) << "\n";
}

// ------------------------------------------------------------
// 4) Tag-dispatched function for float_tag (multiply two floating-point numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_floating_point_v<T> && std::is_floating_point_v<U>, void>
// process_data(float_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a * b) << "\n";  // Product for floating-point types
// }

template <typename A, typename B, std::enable_if_t<std::is_floating_point_v<A> && std::is_floating_point_v<B>>>
void process_data(float_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a * b) << "\n";
}

// ------------------------------------------------------------
// TESTS (do NOT change)
// ------------------------------------------------------------

int main() {
    bool all_ok = true;

    // Test: process_data for int_tag
    std::cout << "[process_data for int_tag]\n";
    std::cout << "int: ";
    process_data(int_tag{}, 10, 20);  // Should print: Result: 30
    std::cout << "float: ";
    process_data(float_tag{}, 3.14f, 2.0f);  // Should print: Result: 6.28
    std::cout << "string: ";
    process_data(int_tag{}, "Hello", "World");  // Should print: <unsupported type>

    return 0;
}
added 27 characters in body
Source Link
Huy Le
  • 2k
  • 1
  • 10
  • 37

Why is the current implementation wrong? Compiled with -std=c++20

Why is the current implementation wrong?

Why is the current implementation wrong? Compiled with -std=c++20

Source Link
Huy Le
  • 2k
  • 1
  • 10
  • 37

C++ template dispatching not calling the correct function

The program test tag dispatching pattern, where the function process_data(tag, a, b) can accept 2 tags int_tag, float_tag. There are 3 case:

  • int_tag and a, b are int -> print a + b
  • float_tag and a,b are float -> print a * b
  • print unsupported for every other case

The correct implementation is inside comment block. I'm trying to implement it another way, but current code always output unsupported isntead of calling the correct int/float version of process_data.

Why is the current implementation wrong?

#include <iostream>
#include <type_traits>
#include <vector>
#include <string>

// ------------------------------------------------------------
// Tag types: int_tag and float_tag
// ------------------------------------------------------------
struct int_tag {};
struct float_tag {};

// ------------------------------------------------------------
// 2) Primary template: process_data (generic version)
// ------------------------------------------------------------
// template <typename Tag, typename T, typename U>
// void process_data(Tag tag, const T& a, const U& b) {
//     std::cout << "<unsupported type>" << "\n";
// }

template <typename Tag, typename A, typename B, typename Enable = void>
void process_data(Tag tag, const A& a, const B& b) {
    std::cout << "<unsupported type>" << "\n";
}

// ------------------------------------------------------------
// 3) Tag-dispatched function for int_tag (sum two integral numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<U>, void>
// process_data(int_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a + b) << "\n";  // Sum for integral types
// }

template <typename A, typename B, std::enable_if_t<std::is_integral_v<A> && std::is_integral_v<B>>>
void process_data(int_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a + b) << "\n";
}

// ------------------------------------------------------------
// 4) Tag-dispatched function for float_tag (multiply two floating-point numbers)
// ------------------------------------------------------------
// template <typename T, typename U>
// std::enable_if_t<std::is_floating_point_v<T> && std::is_floating_point_v<U>, void>
// process_data(float_tag, const T& a, const U& b) {
//     std::cout << "Result: " << (a * b) << "\n";  // Product for floating-point types
// }

template <typename A, typename B, std::enable_if_t<std::is_floating_point_v<A> && std::is_floating_point_v<B>>>
void process_data(float_tag, const A& a, const B& b) {
    std::cout << "Result: " << (a * b) << "\n";
}

// ------------------------------------------------------------
// TESTS (do NOT change)
// ------------------------------------------------------------

int main() {
    bool all_ok = true;

    // Test: process_data for int_tag
    std::cout << "[process_data for int_tag]\n";
    std::cout << "int: ";
    process_data(int_tag{}, 10, 20);  // Should print: Result: 30
    std::cout << "float: ";
    process_data(float_tag{}, 3.14f, 2.0f);  // Should print: Result: 6.28
    std::cout << "string: ";
    process_data(int_tag{}, "Hello", "World");  // Should print: <unsupported type>



    return 0;
}